Use object for logging in.

This commit is contained in:
flash 2019-09-29 19:05:06 +02:00
parent c4cd40eb11
commit f8e8fa4e37
4 changed files with 68 additions and 73 deletions

View file

@ -1,6 +1,8 @@
<?php
namespace Misuzu;
use Misuzu\Users\User;
require_once '../../misuzu.php';
if(user_session_active()) {
@ -41,7 +43,7 @@ while(!empty($_POST['login']) && is_array($_POST['login'])) {
break;
}
$userData = user_find_for_login($_POST['login']['username']);
$userData = User::findForLogin($_POST['login']['username']);
$attemptsRemainingError = sprintf(
"%d attempt%s remaining",
$remainingAttempts - 1,
@ -49,52 +51,52 @@ while(!empty($_POST['login']) && is_array($_POST['login'])) {
);
$loginFailedError = "Invalid username or password, {$attemptsRemainingError}.";
if(empty($userData) || $userData['user_id'] < 1) {
if(empty($userData)) {
user_login_attempt_record(false, null, $ipAddress, $userAgent);
$notices[] = $loginFailedError;
break;
}
if(empty($userData['password'])) {
if(!$userData->hasPassword()) {
$notices[] = 'Your password has been invalidated, please reset it.';
break;
}
if(!is_null($userData['user_deleted']) || !password_verify($_POST['login']['password'], $userData['password'])) {
user_login_attempt_record(false, $userData['user_id'], $ipAddress, $userAgent);
if($userData->isDeleted() || !$userData->checkPassword($_POST['login']['password'])) {
user_login_attempt_record(false, $userData->user_id, $ipAddress, $userAgent);
$notices[] = $loginFailedError;
break;
}
if(user_password_needs_rehash($userData['password'])) {
user_password_set($userData['user_id'], $_POST['login']['password']);
if($userData->passwordNeedsRehash()) {
$userData->setPassword($_POST['login']['password']);
}
if(!empty($loginPermCat) && $loginPermVal > 0 && !perms_check_user($loginPermCat, $userData['user_id'], $loginPermVal)) {
$notices[] = "Login succeeded, but you're not allowed to browse the site right now.";
user_login_attempt_record(true, $userData['user_id'], $ipAddress, $userAgent);
user_login_attempt_record(true, $userData->user_id, $ipAddress, $userAgent);
break;
}
if($userData['totp_enabled']) {
if($userData->hasTOTP()) {
url_redirect('auth-two-factor', [
'token' => user_auth_tfa_token_create($userData['user_id']),
'token' => user_auth_tfa_token_create($userData->user_id),
]);
return;
}
user_login_attempt_record(true, $userData['user_id'], $ipAddress, $userAgent);
$sessionKey = user_session_create($userData['user_id'], $ipAddress, $userAgent);
user_login_attempt_record(true, $userData->user_id, $ipAddress, $userAgent);
$sessionKey = user_session_create($userData->user_id, $ipAddress, $userAgent);
if(empty($sessionKey)) {
$notices[] = "Something broke while creating a session for you, please tell an administrator or developer about this!";
break;
}
user_session_start($userData['user_id'], $sessionKey);
user_session_start($userData->user_id, $sessionKey);
$cookieLife = strtotime(user_session_current('session_expires'));
$cookieValue = base64url_encode(user_session_cookie_pack($userData['user_id'], $sessionKey));
$cookieValue = base64url_encode(user_session_cookie_pack($userData->user_id, $sessionKey));
setcookie('msz_auth', $cookieValue, $cookieLife, '/', '', !empty($_SERVER['HTTPS']), true);
if(!is_local_url($loginRedirect)) {

View file

@ -1,6 +1,8 @@
<?php
namespace Misuzu;
use Misuzu\Users\User;
require_once '../../misuzu.php';
if(user_session_active()) {
@ -66,20 +68,20 @@ while(!$restricted && !empty($register)) {
break;
}
$createUser = user_create(
$createUser = User::create(
$register['username'],
$register['password'],
$register['email'],
$ipAddress
);
if($createUser < 1) {
if($createUser === null) {
$notices[] = 'Something went wrong while creating your account, please alert an administrator or a developer about this!';
break;
}
user_role_add($createUser, MSZ_ROLE_MAIN);
url_redirect('auth-login-welcome', ['username' => $register['username']]);
user_role_add($createUser->user_id, MSZ_ROLE_MAIN);
url_redirect('auth-login-welcome', ['username' => $createUser->username]);
return;
}

View file

@ -32,16 +32,13 @@ class User {
string $ipAddress
): ?User {
$createUser = DB::prepare('
INSERT INTO `msz_users`
(
`username`, `password`, `email`, `register_ip`,
`last_ip`, `user_country`, `display_role`
)
VALUES
(
:username, :password, LOWER(:email), INET6_ATON(:register_ip),
INET6_ATON(:last_ip), :user_country, 1
)
INSERT INTO `msz_users` (
`username`, `password`, `email`, `register_ip`,
`last_ip`, `user_country`, `display_role`
) VALUES (
:username, :password, LOWER(:email), INET6_ATON(:register_ip),
INET6_ATON(:last_ip), :user_country, 1
)
') ->bind('username', $username)->bind('email', $email)
->bind('register_ip', $ipAddress)->bind('last_ip', $ipAddress)
->bind('password', user_password_hash($password))
@ -55,8 +52,46 @@ class User {
}
public static function get(int $userId): ?User {
return DB::prepare(self::USER_SELECT . 'WHERE `user_id` = :user_id')
return DB::prepare(self::USER_SELECT . 'WHERE `user_id` = :user_id')
->bind('user_id', $userId)
->fetchObject(User::class);
}
public static function findForLogin(string $usernameOrEmail): ?User {
return DB::prepare(self::USER_SELECT . 'WHERE LOWER(`email`) = LOWER(:email) OR LOWER(`username`) = LOWER(:username)')
->bind('email', $usernameOrEmail)
->bind('username', $usernameOrEmail)
->fetchObject(User::class);
}
public function hasUserId(): bool {
return isset($this->user_id) && $this->user_id > 0;
}
public function hasPassword(): bool {
return !empty($this->password);
}
public function checkPassword(string $password): bool {
return $this->hasPassword() && password_verify($password, $this->password);
}
public function passwordNeedsRehash(): bool {
return password_needs_rehash($this->password, MSZ_USERS_PASSWORD_HASH_ALGO);
}
public function setPassword(string $password): void {
if(!$this->hasUserId())
return;
DB::prepare('UPDATE `msz_users` SET `password` = :password WHERE `user_id` = :user_id')
->bind('password', password_hash($password, MSZ_USERS_PASSWORD_HASH_ALGO))
->bind('user_id', $this->user_id)
->execute();
}
public function isDeleted(): bool {
return !empty($this->user_deleted);
}
public function hasTOTP(): bool {
return !empty($this->user_totp_key);
}
}

View file

@ -28,46 +28,6 @@ define(
)
);
function user_create(
string $username,
string $password,
string $email,
string $ipAddress
): int {
$createUser = \Misuzu\DB::prepare('
INSERT INTO `msz_users`
(
`username`, `password`, `email`, `register_ip`,
`last_ip`, `user_country`, `display_role`
)
VALUES
(
:username, :password, LOWER(:email), INET6_ATON(:register_ip),
INET6_ATON(:last_ip), :user_country, 1
)
');
$createUser->bind('username', $username);
$createUser->bind('password', user_password_hash($password));
$createUser->bind('email', $email);
$createUser->bind('register_ip', $ipAddress);
$createUser->bind('last_ip', $ipAddress);
$createUser->bind('user_country', ip_country_code($ipAddress));
return $createUser->execute() ? \Misuzu\DB::lastId() : 0;
}
function user_find_for_login(string $usernameOrMail): array {
$getUser = \Misuzu\DB::prepare('
SELECT `user_id`, `password`, `user_totp_key` IS NOT NULL AS `totp_enabled`, `user_deleted`
FROM `msz_users`
WHERE LOWER(`email`) = LOWER(:email)
OR LOWER(`username`) = LOWER(:username)
');
$getUser->bind('email', $usernameOrMail);
$getUser->bind('username', $usernameOrMail);
return $getUser->fetch();
}
function user_find_for_reset(string $email): array {
$getUser = \Misuzu\DB::prepare('
SELECT `user_id`, `username`, `email`
@ -99,10 +59,6 @@ function user_password_hash(string $password): string {
return password_hash($password, MSZ_USERS_PASSWORD_HASH_ALGO);
}
function user_password_needs_rehash(string $hash): bool {
return password_needs_rehash($hash, MSZ_USERS_PASSWORD_HASH_ALGO);
}
function user_password_set(int $userId, string $password): bool {
$updatePassword = \Misuzu\DB::prepare('
UPDATE `msz_users`