From 865ecc87963dc3b26e66296616eef2a1cc41ac3f Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Wed, 25 Oct 2023 12:55:09 +0300 Subject: move to psr-4 autoloader --- classes/userhelper.php | 520 ------------------------------------------------- 1 file changed, 520 deletions(-) delete mode 100644 classes/userhelper.php (limited to 'classes/userhelper.php') diff --git a/classes/userhelper.php b/classes/userhelper.php deleted file mode 100644 index 4d9f30548..000000000 --- a/classes/userhelper.php +++ /dev/null @@ -1,520 +0,0 @@ -chain_hooks_callback(PluginHost::HOOK_AUTH_USER, - function ($result, $plugin) use (&$user_id, &$auth_module) { - if ($result) { - $user_id = (int)$result; - $auth_module = strtolower(get_class($plugin)); - return true; - } - }, - $login, $password, $service); - - if ($user_id && !$check_only) { - - if (session_status() != PHP_SESSION_ACTIVE) - session_start(); - - session_regenerate_id(true); - - $user = ORM::for_table('ttrss_users')->find_one($user_id); - - if ($user && $user->access_level != self::ACCESS_LEVEL_DISABLED) { - self::set_session_for_user($user_id); - $_SESSION["auth_module"] = $auth_module; - $_SESSION["name"] = $user->login; - $_SESSION["access_level"] = $user->access_level; - $_SESSION["pwd_hash"] = $user->pwd_hash; - - $user->last_login = Db::NOW(); - $user->save(); - - return true; - } - - return false; - } - - if ($login && $password && !$user_id && !$check_only) - Logger::log(E_USER_WARNING, "Failed login attempt for $login (service: $service) from " . UserHelper::get_user_ip()); - - return false; - - } else { - self::set_session_for_user(1); - $_SESSION["name"] = "admin"; - $_SESSION["access_level"] = self::ACCESS_LEVEL_ADMIN; - - $_SESSION["hide_hello"] = true; - $_SESSION["hide_logout"] = true; - - $_SESSION["auth_module"] = false; - - return true; - } - } - - static function set_session_for_user(int $owner_uid): void { - $_SESSION["uid"] = $owner_uid; - $_SESSION["last_login_update"] = time(); - $_SESSION["ip_address"] = UserHelper::get_user_ip(); - - if (empty($_SESSION["csrf_token"])) - $_SESSION["csrf_token"] = bin2hex(get_random_bytes(16)); - - if (Config::get_schema_version() >= 120) { - $_SESSION["language"] = get_pref(Prefs::USER_LANGUAGE, $owner_uid); - } - } - - static function load_user_plugins(int $owner_uid, PluginHost $pluginhost = null): void { - - if (!$pluginhost) $pluginhost = PluginHost::getInstance(); - - if ($owner_uid && Config::get_schema_version() >= 100 && empty($_SESSION["safe_mode"])) { - $plugins = get_pref(Prefs::_ENABLED_PLUGINS, $owner_uid); - - $pluginhost->load((string)$plugins, PluginHost::KIND_USER, $owner_uid); - - /*if (get_schema_version() > 100) { - $pluginhost->load_data(); - }*/ - } - } - - static function login_sequence(): void { - $pdo = Db::pdo(); - - if (Config::get(Config::SINGLE_USER_MODE)) { - if (session_status() != PHP_SESSION_ACTIVE) - session_start(); - - self::authenticate("admin", null); - startup_gettext(); - self::load_user_plugins($_SESSION["uid"]); - } else { - if (!\Sessions\validate_session()) - $_SESSION["uid"] = null; - - if (empty($_SESSION["uid"])) { - - if (Config::get(Config::AUTH_AUTO_LOGIN) && self::authenticate(null, null)) { - $_SESSION["ref_schema_version"] = Config::get_schema_version(); - } else { - self::authenticate(null, null, true); - } - - if (empty($_SESSION["uid"])) { - UserHelper::logout(); - - Handler_Public::_render_login_form(); - exit; - } - - } else { - /* bump login timestamp */ - $user = ORM::for_table('ttrss_users')->find_one($_SESSION["uid"]); - $user->last_login = Db::NOW(); - $user->save(); - - $_SESSION["last_login_update"] = time(); - } - - if ($_SESSION["uid"]) { - startup_gettext(); - self::load_user_plugins($_SESSION["uid"]); - } - } - } - - static function print_user_stylesheet(): void { - $value = get_pref(Prefs::USER_STYLESHEET); - - if ($value) { - print ""; - } - - } - - static function get_user_ip(): ?string { - foreach (["HTTP_X_REAL_IP", "REMOTE_ADDR"] as $hdr) { - if (isset($_SERVER[$hdr])) - return $_SERVER[$hdr]; - } - - return null; - } - - static function get_login_by_id(int $id): ?string { - $user = ORM::for_table('ttrss_users') - ->find_one($id); - - if ($user) - return $user->login; - else - return null; - } - - static function find_user_by_login(string $login): ?int { - $user = ORM::for_table('ttrss_users') - ->where('login', $login) - ->find_one(); - - if ($user) - return $user->id; - else - return null; - } - - static function logout(): void { - if (session_status() === PHP_SESSION_ACTIVE) - session_destroy(); - - if (isset($_COOKIE[session_name()])) { - setcookie(session_name(), '', time()-42000, '/'); - - } - session_commit(); - } - - static function get_salt(): string { - return substr(bin2hex(get_random_bytes(125)), 0, 250); - } - - /** TODO: this should invoke UserHelper::user_modify() */ - static function reset_password(int $uid, bool $format_output = false, string $new_password = ""): void { - - $user = ORM::for_table('ttrss_users')->find_one($uid); - $message = ""; - - if ($user) { - - $login = $user->login; - - $new_salt = self::get_salt(); - $tmp_user_pwd = $new_password ? $new_password : make_password(); - - $pwd_hash = self::hash_password($tmp_user_pwd, $new_salt, self::HASH_ALGOS[0]); - - $user->pwd_hash = $pwd_hash; - $user->salt = $new_salt; - $user->save(); - - $message = T_sprintf("Changed password of user %s to %s", "$login", "$tmp_user_pwd"); - } else { - $message = __("User not found"); - } - - if ($format_output) - print_notice($message); - else - print $message; - } - - static function check_otp(int $owner_uid, int $otp_check) : bool { - $otp = TOTP::create(self::get_otp_secret($owner_uid, true)); - - return $otp->now() == $otp_check; - } - - static function disable_otp(int $owner_uid) : bool { - $user = ORM::for_table('ttrss_users')->find_one($owner_uid); - - if ($user) { - $user->otp_enabled = false; - - // force new OTP secret when next enabled - if (Config::get_schema_version() >= 143) { - $user->otp_secret = null; - } - - $user->save(); - - return true; - } else { - return false; - } - } - - static function enable_otp(int $owner_uid, int $otp_check) : bool { - $secret = self::get_otp_secret($owner_uid); - - if ($secret) { - $otp = TOTP::create($secret); - $user = ORM::for_table('ttrss_users')->find_one($owner_uid); - - if ($otp->now() == $otp_check && $user) { - - $user->otp_enabled = true; - $user->save(); - - return true; - } - } - return false; - } - - - static function is_otp_enabled(int $owner_uid) : bool { - $user = ORM::for_table('ttrss_users')->find_one($owner_uid); - - if ($user) { - return $user->otp_enabled; - } else { - return false; - } - } - - static function get_otp_secret(int $owner_uid, bool $show_if_enabled = false): ?string { - $user = ORM::for_table('ttrss_users')->find_one($owner_uid); - - if ($user) { - - $salt_based_secret = mb_substr(sha1($user->salt), 0, 12); - - if (Config::get_schema_version() >= 143) { - $secret = $user->otp_secret; - - if (empty($secret)) { - - /* migrate secret if OTP is already enabled, otherwise make a new one */ - if ($user->otp_enabled) { - $user->otp_secret = $salt_based_secret; - } else { - $user->otp_secret = bin2hex(get_random_bytes(10)); - } - - $user->save(); - - $secret = $user->otp_secret; - } - } else { - $secret = $salt_based_secret; - } - - if (!$user->otp_enabled || $show_if_enabled) { - return \ParagonIE\ConstantTime\Base32::encodeUpperUnpadded($secret); - } - } - - return null; - } - - /** - * @param null|int $owner_uid if null, checks current user via session-specific auth module, if set works on internal database only - * @return bool - * @throws PDOException - * @throws Exception - */ - static function is_default_password(?int $owner_uid = null): bool { - return self::user_has_password($owner_uid, 'password'); - } - - /** - * @param string $algo should be one of UserHelper::HASH_ALGO_* - * - * @return false|string False if the password couldn't be hashed, otherwise the hash string. - */ - static function hash_password(string $pass, string $salt, string $algo = self::HASH_ALGOS[0]) { - $pass_hash = ""; - - switch ($algo) { - case self::HASH_ALGO_SHA1: - $pass_hash = sha1($pass); - break; - case self::HASH_ALGO_SHA1X: - $pass_hash = sha1("$salt:$pass"); - break; - case self::HASH_ALGO_MODE2: - case self::HASH_ALGO_SSHA256: - $pass_hash = hash('sha256', $salt . $pass); - break; - case self::HASH_ALGO_SSHA512: - $pass_hash = hash('sha512', $salt . $pass); - break; - default: - user_error("hash_password: unknown hash algo: $algo", E_USER_ERROR); - } - - if ($pass_hash) - return "$algo:$pass_hash"; - else - return false; - } - - /** - * @param string $login Login for new user (case-insensitive) - * @param string $password Password for new user (may not be blank) - * @param UserHelper::ACCESS_LEVEL_* $access_level Access level for new user - * @return bool true if user has been created - */ - static function user_add(string $login, string $password, int $access_level) : bool { - $login = clean($login); - - if ($login && - $password && - !self::find_user_by_login($login) && - self::map_access_level((int)$access_level) != self::ACCESS_LEVEL_KEEP_CURRENT) { - - $user = ORM::for_table('ttrss_users')->create(); - - $user->salt = self::get_salt(); - $user->login = mb_strtolower($login); - $user->pwd_hash = self::hash_password($password, $user->salt); - $user->access_level = $access_level; - $user->created = Db::NOW(); - - return $user->save(); - } - - return false; - } - - /** - * @param int $uid User ID to modify - * @param string $new_password set password to this value if its not blank - * @param UserHelper::ACCESS_LEVEL_* $access_level set user access level to this value if it is set (default ACCESS_LEVEL_KEEP_CURRENT) - * @return bool true if user record has been saved - * - * NOTE: $access_level is of mixed type because of intellephense - */ - static function user_modify(int $uid, string $new_password = '', $access_level = self::ACCESS_LEVEL_KEEP_CURRENT) : bool { - $user = ORM::for_table('ttrss_users')->find_one($uid); - - if ($user) { - if ($new_password != '') { - $new_salt = self::get_salt(); - $pwd_hash = self::hash_password($new_password, $new_salt, self::HASH_ALGOS[0]); - - $user->pwd_hash = $pwd_hash; - $user->salt = $new_salt; - } - - if ($access_level != self::ACCESS_LEVEL_KEEP_CURRENT) { - $user->access_level = (int)$access_level; - } - - return $user->save(); - } - - return false; - } - - /** - * @param int $uid user ID to delete (this won't delete built-in admin user with UID 1) - * @return bool true if user has been deleted - */ - static function user_delete(int $uid) : bool { - if ($uid != 1) { - - $user = ORM::for_table('ttrss_users')->find_one($uid); - - if ($user) { - // TODO: is it still necessary to split those queries? - - ORM::for_table('ttrss_tags') - ->where('owner_uid', $uid) - ->delete_many(); - - ORM::for_table('ttrss_feeds') - ->where('owner_uid', $uid) - ->delete_many(); - - return $user->delete(); - } - } - - return false; - } - - /** - * @param null|int $owner_uid if null, checks current user via session-specific auth module, if set works on internal database only - * @param string $password password to compare hash against - * @return bool - */ - static function user_has_password(?int $owner_uid, string $password) : bool { - if ($owner_uid) { - $authenticator = new Auth_Internal(); - - return $authenticator->check_password($owner_uid, $password); - } else { - /** @var Auth_Internal|false $authenticator -- this is only here to make check_password() visible to static analyzer */ - $authenticator = PluginHost::getInstance()->get_plugin($_SESSION["auth_module"]); - - if ($authenticator && - method_exists($authenticator, "check_password") && - $authenticator->check_password($_SESSION["uid"], $password)) { - - return true; - } - } - - return false; - } - -} -- cgit v1.2.3