'Your username may not start or end with spaces!', 'short' => "Your username is too short, it has to be at least " . User::USERNAME_MIN_LENGTH . " characters!", 'long' => "Your username is too long, it can't be longer than " . User::USERNAME_MAX_LENGTH . " characters!", 'double-spaces' => "Your username can't contain double spaces.", 'invalid' => 'Your username contains invalid characters.', 'spacing' => 'Please use either underscores or spaces, not both!', ]; public function login() { $app = Application::getInstance(); if ($app->getSession() !== null) { return ''; } if ($_SERVER['REQUEST_METHOD'] === 'GET') { $twig = $app->templating; return $twig->render('auth.login'); } if (!isset($_POST['username'], $_POST['password'])) { return ['error' => "You didn't fill all the forms!"]; } $username = $_POST['username'] ?? ''; $password = $_POST['password'] ?? ''; try { $user = User::where('username', $username)->orWhere('email', $username)->firstOrFail(); } catch (ModelNotFoundException $e) { return ['error' => 'Invalid username or password!']; } if (!$user->validatePassword($password)) { return ['error' => 'Invalid username or password!']; } $session = Session::createSession($user, 'Misuzu T1'); $app->setSession($session); $this->setCookie('uid', $session->user_id, 604800); $this->setCookie('sid', $session->session_key, 604800); // Temporary key generation for chat login. // Should eventually be replaced with a callback login system. // Also uses different cookies since $httponly is required to be false for these. $user->last_ip = IP::remote(); $user->user_chat_key = bin2hex(random_bytes(16)); $user->save(); setcookie('msz_tmp_id', $user->user_id, time() + 604800, '/', '.flashii.net'); setcookie('msz_tmp_key', $user->user_chat_key, time() + 604800, '/', '.flashii.net'); return ['error' => 'You are now logged in!', 'next' => '/']; } private function setCookie(string $name, string $value, int $expires): void { setcookie( "msz_{$name}", $value, time() + $expires, '/', '', !empty($_SERVER['HTTPS']), true ); } public function register() { $app = Application::getInstance(); if ($app->getSession() !== null) { return ''; } if ($_SERVER['REQUEST_METHOD'] === 'GET') { $twig = $app->templating; return $twig->render('auth.register'); } if (!isset($_POST['username'], $_POST['password'], $_POST['email'])) { return ['error' => "You didn't fill all the forms!"]; } $username = $_POST['username'] ?? ''; $username_validate = User::validateUsername($username); $password = $_POST['password'] ?? ''; $email = $_POST['email'] ?? ''; if ($username_validate !== '') { return ['error' => self::USERNAME_VALIDATION_ERRORS[$username_validate]]; } try { $existing = User::where('username', $username)->firstOrFail(); if ($existing->user_id > 0) { return ['error' => 'This username is already taken!']; } } catch (ModelNotFoundException $e) { } if (!filter_var($email, FILTER_VALIDATE_EMAIL) || !check_mx_record($email)) { return ['error' => 'The e-mail address you entered is invalid!']; } try { $existing = User::where('email', $email)->firstOrFail(); if ($existing->user_id > 0) { return ['error' => 'This e-mail address has already been used!']; } } catch (ModelNotFoundException $e) { } if (password_entropy($password) < 32) { return ['error' => 'Your password is considered too weak!']; } User::createUser($username, $password, $email); return ['error' => 'Welcome to Flashii! You may now log in.', 'next' => '/auth/login']; } public function logout() { $app = Application::getInstance(); $session = $app->getSession(); if ($session === null) { echo "You aren't logged in."; } else { echo "You've been logged out."; $this->setCookie('uid', '', -3600); $this->setCookie('sid', '', -3600); $session->delete(); $app->setSession(null); } return ''; } }