diff options
Diffstat (limited to 'classes')
-rwxr-xr-x | classes/feeds.php | 7 | ||||
-rw-r--r-- | classes/handler/administrative.php | 2 | ||||
-rwxr-xr-x | classes/pref/feeds.php | 12 | ||||
-rw-r--r-- | classes/pref/prefs.php | 16 | ||||
-rwxr-xr-x | classes/rpc.php | 7 | ||||
-rwxr-xr-x | classes/rssutils.php | 19 | ||||
-rw-r--r-- | classes/userhelper.php | 19 |
7 files changed, 66 insertions, 16 deletions
diff --git a/classes/feeds.php b/classes/feeds.php index 987123a21..cd2633ffb 100755 --- a/classes/feeds.php +++ b/classes/feeds.php @@ -1027,10 +1027,17 @@ class Feeds extends Handler_Protected { * 5 - Couldn't download the URL content. * 6 - Content is an invalid XML. * 7 - Error while creating feed database entry. + * 8 - Permission denied (ACCESS_LEVEL_READONLY). */ static function _subscribe($url, $cat_id = 0, $auth_login = '', $auth_pass = '') : array { + $user = ORM::for_table("ttrss_users")->find_one($_SESSION['uid']); + + if ($user && $user->access_level == UserHelper::ACCESS_LEVEL_READONLY) { + return ["code" => 8]; + } + $pdo = Db::pdo(); $url = UrlHelper::validate($url); diff --git a/classes/handler/administrative.php b/classes/handler/administrative.php index 52dfed8b7..f2f5b36ba 100644 --- a/classes/handler/administrative.php +++ b/classes/handler/administrative.php @@ -2,7 +2,7 @@ class Handler_Administrative extends Handler_Protected { function before($method) { if (parent::before($method)) { - if (($_SESSION["access_level"] ?? 0) >= 10) { + if (($_SESSION["access_level"] ?? 0) >= UserHelper::ACCESS_LEVEL_ADMIN) { return true; } } diff --git a/classes/pref/feeds.php b/classes/pref/feeds.php index 95bbcd190..ac0874259 100755 --- a/classes/pref/feeds.php +++ b/classes/pref/feeds.php @@ -538,6 +538,8 @@ class Pref_Feeds extends Handler_Protected { $local_purge_intervals = [ T_nsprintf('%d day', '%d days', $purge_interval, $purge_interval) ]; } + $user = ORM::for_table("ttrss_users")->find_one($_SESSION["uid"]); + print json_encode([ "feed" => $row, "cats" => [ @@ -550,6 +552,9 @@ class Pref_Feeds extends Handler_Protected { "update" => $local_update_intervals, "purge" => $local_purge_intervals, ], + "user" => [ + "access_level" => $user->access_level + ], "lang" => [ "enabled" => Config::get(Config::DB_TYPE) == "pgsql", "default" => get_pref(Prefs::DEFAULT_SEARCH_LANGUAGE), @@ -1207,6 +1212,13 @@ class Pref_Feeds extends Handler_Protected { $login = clean($_REQUEST['login']); $pass = clean($_REQUEST['pass']); + $user = ORM::for_table('ttrss_users')->find_one($_SESSION["uid"]); + + // TODO: we should return some kind of error code to frontend here + if ($user->access_level == UserHelper::ACCESS_LEVEL_READONLY) { + return false; + } + $csth = $this->pdo->prepare("SELECT id FROM ttrss_feeds WHERE feed_url = ? AND owner_uid = ?"); diff --git a/classes/pref/prefs.php b/classes/pref/prefs.php index c47a99469..c45d6d6ea 100644 --- a/classes/pref/prefs.php +++ b/classes/pref/prefs.php @@ -813,7 +813,7 @@ class Pref_Prefs extends Handler_Protected { usort($rv, function($a, $b) { return strcmp($a["name"], $b["name"]); }); - print json_encode(['plugins' => $rv, 'is_admin' => $_SESSION['access_level'] >= 10]); + print json_encode(['plugins' => $rv, 'is_admin' => $_SESSION['access_level'] >= UserHelper::ACCESS_LEVEL_ADMIN]); } function index_plugins() { @@ -890,7 +890,7 @@ class Pref_Prefs extends Handler_Protected { <?= \Controls\button_tag(\Controls\icon("refresh"), "", ["title" => __("Reload"), "onclick" => "Helpers.Plugins.reload()"]) ?> - <?php if ($_SESSION["access_level"] >= 10) { ?> + <?php if ($_SESSION["access_level"] >= UserHelper::ACCESS_LEVEL_ADMIN) { ?> <?php if (Config::get(Config::CHECK_FOR_UPDATES) && Config::get(Config::CHECK_FOR_PLUGIN_UPDATES)) { ?> <button class='alt-warning' dojoType='dijit.form.Button' onclick="Helpers.Plugins.update()"> @@ -1152,7 +1152,7 @@ class Pref_Prefs extends Handler_Protected { } function uninstallPlugin() { - if ($_SESSION["access_level"] >= 10) { + if ($_SESSION["access_level"] >= UserHelper::ACCESS_LEVEL_ADMIN) { $plugin_name = basename(clean($_REQUEST['plugin'])); $status = 0; @@ -1167,7 +1167,7 @@ class Pref_Prefs extends Handler_Protected { } function installPlugin() { - if ($_SESSION["access_level"] >= 10 && Config::get(Config::ENABLE_PLUGIN_INSTALLER)) { + if ($_SESSION["access_level"] >= UserHelper::ACCESS_LEVEL_ADMIN && Config::get(Config::ENABLE_PLUGIN_INSTALLER)) { $plugin_name = basename(clean($_REQUEST['plugin'])); $all_plugins = $this->_get_available_plugins(); $plugin_dir = dirname(dirname(__DIR__)) . "/plugins.local"; @@ -1252,18 +1252,18 @@ class Pref_Prefs extends Handler_Protected { } private function _get_available_plugins() { - if ($_SESSION["access_level"] >= 10 && Config::get(Config::ENABLE_PLUGIN_INSTALLER)) { + if ($_SESSION["access_level"] >= UserHelper::ACCESS_LEVEL_ADMIN && Config::get(Config::ENABLE_PLUGIN_INSTALLER)) { return json_decode(UrlHelper::fetch(['url' => 'https://tt-rss.org/plugins.json']), true); } } function getAvailablePlugins() { - if ($_SESSION["access_level"] >= 10) { + if ($_SESSION["access_level"] >= UserHelper::ACCESS_LEVEL_ADMIN) { print json_encode($this->_get_available_plugins()); } } function checkForPluginUpdates() { - if ($_SESSION["access_level"] >= 10 && Config::get(Config::CHECK_FOR_UPDATES) && Config::get(Config::CHECK_FOR_PLUGIN_UPDATES)) { + if ($_SESSION["access_level"] >= UserHelper::ACCESS_LEVEL_ADMIN && Config::get(Config::CHECK_FOR_UPDATES) && Config::get(Config::CHECK_FOR_PLUGIN_UPDATES)) { $plugin_name = $_REQUEST["name"] ?? ""; $root_dir = dirname(dirname(__DIR__)); # we're in classes/pref/ @@ -1279,7 +1279,7 @@ class Pref_Prefs extends Handler_Protected { } function updateLocalPlugins() { - if ($_SESSION["access_level"] >= 10) { + if ($_SESSION["access_level"] >= UserHelper::ACCESS_LEVEL_ADMIN) { $plugins = explode(",", $_REQUEST["plugins"] ?? ""); # we're in classes/pref/ diff --git a/classes/rpc.php b/classes/rpc.php index b6c4a5fc9..0432ed2d3 100755 --- a/classes/rpc.php +++ b/classes/rpc.php @@ -299,7 +299,8 @@ class RPC extends Handler_Protected { ttrss_feeds f, ttrss_users u LEFT JOIN ttrss_user_prefs2 p ON (p.owner_uid = u.id AND profile IS NULL AND pref_name = 'DEFAULT_UPDATE_INTERVAL') WHERE - f.owner_uid = u.id + f.owner_uid = u.id AND + u.access_level NOT IN (".sprintf("%d, %d", UserHelper::ACCESS_LEVEL_DISABLED, UserHelper::ACCESS_LEVEL_READONLY).") $owner_check_qpart $update_limit_qpart $updstart_thresh_qpart @@ -403,7 +404,7 @@ class RPC extends Handler_Protected { $git_timestamp = $version["timestamp"] ?? false; $git_commit = $version["commit"] ?? false; - if (Config::get(Config::CHECK_FOR_UPDATES) && $_SESSION["access_level"] >= 10 && $git_timestamp) { + if (Config::get(Config::CHECK_FOR_UPDATES) && $_SESSION["access_level"] >= UserHelper::ACCESS_LEVEL_ADMIN && $git_timestamp) { $content = @UrlHelper::fetch(["url" => "https://tt-rss.org/version.json"]); if ($content) { @@ -510,7 +511,7 @@ class RPC extends Handler_Protected { $data['cdm_expanded'] = get_pref(Prefs::CDM_EXPANDED); $data["labels"] = Labels::get_all($_SESSION["uid"]); - if (Config::get(Config::LOG_DESTINATION) == 'sql' && $_SESSION['access_level'] >= 10) { + if (Config::get(Config::LOG_DESTINATION) == 'sql' && $_SESSION['access_level'] >= UserHelper::ACCESS_LEVEL_ADMIN) { if (Config::get(Config::DB_TYPE) == 'pgsql') { $log_interval = "created_at > NOW() - interval '1 hour'"; } else { diff --git a/classes/rssutils.php b/classes/rssutils.php index 87e52ba42..927a6c251 100755 --- a/classes/rssutils.php +++ b/classes/rssutils.php @@ -123,7 +123,8 @@ class RSSUtils { ttrss_feeds f, ttrss_users u LEFT JOIN ttrss_user_prefs2 p ON (p.owner_uid = u.id AND profile IS NULL AND pref_name = 'DEFAULT_UPDATE_INTERVAL') WHERE - f.owner_uid = u.id + f.owner_uid = u.id AND + u.access_level NOT IN (".sprintf("%d, %d", UserHelper::ACCESS_LEVEL_DISABLED, UserHelper::ACCESS_LEVEL_READONLY).") $login_thresh_qpart $update_limit_qpart $updstart_thresh_qpart @@ -163,7 +164,8 @@ class RSSUtils { FROM ttrss_feeds f, ttrss_users u LEFT JOIN ttrss_user_prefs2 p ON (p.owner_uid = u.id AND profile IS NULL AND pref_name = 'DEFAULT_UPDATE_INTERVAL') WHERE - f.owner_uid = u.id + f.owner_uid = u.id AND + u.access_level NOT IN (".sprintf("%d, %d", UserHelper::ACCESS_LEVEL_DISABLED, UserHelper::ACCESS_LEVEL_READONLY).") AND feed_url = :feed $login_thresh_qpart $update_limit_qpart @@ -352,6 +354,19 @@ class RSSUtils { if (!$feed_language) $feed_language = mb_strtolower(get_pref(Prefs::DEFAULT_SEARCH_LANGUAGE, $feed_obj->owner_uid)); if (!$feed_language) $feed_language = 'simple'; + $user = ORM::for_table('ttrss_users')->find_one($feed_obj->owner_uid); + + if ($user) { + if ($user->access_level == UserHelper::ACCESS_LEVEL_READONLY) { + Debug::log("error: denied update for $feed: permission denied by owner access level"); + return false; + } + } else { + // this would indicate database corruption of some kind + Debug::log("error: owner not found for feed: $feed"); + return false; + } + } else { Debug::log("error: feeds table record not found for feed: $feed"); return false; diff --git a/classes/userhelper.php b/classes/userhelper.php index 1cdd320a1..ea714b76b 100644 --- a/classes/userhelper.php +++ b/classes/userhelper.php @@ -17,6 +17,21 @@ class UserHelper { self::HASH_ALGO_SHA1 ]; + /** forbidden to login */ + const ACCESS_LEVEL_DISABLED = -2; + + /** can't subscribe to new feeds, feeds are not updated */ + const ACCESS_LEVEL_READONLY = -1; + + /** no restrictions, regular user */ + const ACCESS_LEVEL_USER = 0; + + /** not used, same as regular user */ + const ACCESS_LEVEL_POWERUSER = 5; + + /** has administrator permissions */ + const ACCESS_LEVEL_ADMIN = 10; + static function authenticate(string $login = null, string $password = null, bool $check_only = false, string $service = null) { if (!Config::get(Config::SINGLE_USER_MODE)) { $user_id = false; @@ -41,7 +56,7 @@ class UserHelper { $user = ORM::for_table('ttrss_users')->find_one($user_id); - if ($user) { + if ($user && $user->access_level != self::ACCESS_LEVEL_DISABLED) { $_SESSION["uid"] = $user_id; $_SESSION["auth_module"] = $auth_module; $_SESSION["name"] = $user->login; @@ -68,7 +83,7 @@ class UserHelper { $_SESSION["uid"] = 1; $_SESSION["name"] = "admin"; - $_SESSION["access_level"] = 10; + $_SESSION["access_level"] = self::ACCESS_LEVEL_ADMIN; $_SESSION["hide_hello"] = true; $_SESSION["hide_logout"] = true; |