diff --git a/src/invidious/config.cr b/src/invidious/config.cr index 36cb40a3..59380cb8 100644 --- a/src/invidious/config.cr +++ b/src/invidious/config.cr @@ -71,6 +71,37 @@ struct HTTPProxyConfig property port : Int32 end +# Structure used for global per-page feature toggles +struct PagesEnabled + include YAML::Serializable + + property trending : Bool = true + property popular : Bool = true + property search : Bool = true + + def has_key?(key : String) : Bool + %w(trending popular search).includes?(key) + end + + def [](key : String) : Bool + case key + when "trending" then @trending + when "popular" then @popular + when "search" then @search + else raise KeyError.new("Unknown page '#{key}'") + end + end + + def []=(key : String, value : Bool) + case key + when "trending" then @trending = value + when "popular" then @popular = value + when "search" then @search = value + else raise KeyError.new("Unknown page '#{key}'") + end + end +end + class Config include YAML::Serializable @@ -127,11 +158,7 @@ class Config # Global per-page feature toggles. # Valid keys: "trending", "popular", "search" # If someone sets both `popular_enabled` and `pages_enabled["popular"]`, the latter takes precedence. - property pages_enabled : Hash(String, Bool) = { - "trending" => true, - "popular" => true, - "search" => true, - } + property pages_enabled : PagesEnabled = PagesEnabled.new # ————————————————————————————————————————————————————————————————————————————————————— property captcha_enabled : Bool = true @@ -212,10 +239,10 @@ class Config # Centralized page toggle with legacy fallback for `popular_enabled` def page_enabled?(page : String) : Bool - if pages_enabled.has_key?(page) - pages_enabled[page] + if @pages_enabled.has_key?(page) + @pages_enabled[page] elsif page == "popular" - popular_enabled + @popular_enabled else true end diff --git a/src/invidious/routes/api/v1/feeds.cr b/src/invidious/routes/api/v1/feeds.cr index bfec4fb6..2e8328cb 100644 --- a/src/invidious/routes/api/v1/feeds.cr +++ b/src/invidious/routes/api/v1/feeds.cr @@ -4,11 +4,6 @@ module Invidious::Routes::API::V1::Feeds env.response.content_type = "application/json" - if !CONFIG.page_enabled?("trending") - error_message = {"error" => "Administrator has disabled this endpoint."}.to_json - haltf env, 403, error_message - end - region = env.params.query["region"]? trending_type = env.params.query["type"]? @@ -34,11 +29,6 @@ module Invidious::Routes::API::V1::Feeds env.response.content_type = "application/json" - if !CONFIG.page_enabled?("popular") - error_message = {"error" => "Administrator has disabled this endpoint."}.to_json - haltf env, 403, error_message - end - JSON.build do |json| json.array do popular_videos.each do |video| diff --git a/src/invidious/routes/api/v1/search.cr b/src/invidious/routes/api/v1/search.cr index 3d978c17..59a30745 100644 --- a/src/invidious/routes/api/v1/search.cr +++ b/src/invidious/routes/api/v1/search.cr @@ -5,11 +5,6 @@ module Invidious::Routes::API::V1::Search env.response.content_type = "application/json" - if !CONFIG.page_enabled?("search") - error_message = {"error" => "Administrator has disabled this endpoint."}.to_json - haltf env, 403, error_message - end - query = Invidious::Search::Query.new(env.params.query, :regular, region) begin diff --git a/src/invidious/routes/before_all.cr b/src/invidious/routes/before_all.cr index b5269668..5f6a1daa 100644 --- a/src/invidious/routes/before_all.cr +++ b/src/invidious/routes/before_all.cr @@ -102,6 +102,28 @@ module Invidious::Routes::BeforeAll preferences.locale = locale env.set "preferences", preferences + path = env.request.path + page_key = case path + when "/feed/popular", "/api/v1/popular" + "popular" + when "/feed/trending", "/api/v1/trending" + "trending" + when "/search", "/api/v1/search" + "search" + else + nil + end + + if page_key && !CONFIG.page_enabled?(page_key) + if path.starts_with?("/api/") + error_message = {error: "Administrator has disabled this endpoint."}.to_json + haltf env, 403, error_message + else + message = "#{page_key}_page_disabled" + return error_template(403, message) + end + end + # Allow media resources to be loaded from google servers # TODO: check if *.youtube.com can be removed # diff --git a/src/invidious/routes/feeds.cr b/src/invidious/routes/feeds.cr index c1852f5e..de82e1fb 100644 --- a/src/invidious/routes/feeds.cr +++ b/src/invidious/routes/feeds.cr @@ -33,36 +33,24 @@ module Invidious::Routes::Feeds def self.popular(env) locale = env.get("preferences").as(Preferences).locale - - if CONFIG.page_enabled?("popular") - templated "feeds/popular" - else - message = translate(locale, "popular_page_disabled") - templated "message" - end + templated "feeds/popular" end def self.trending(env) locale = env.get("preferences").as(Preferences).locale + trending_type = env.params.query["type"]? + trending_type ||= "Default" - if CONFIG.page_enabled?("trending") - trending_type = env.params.query["type"]? - trending_type ||= "Default" + region = env.params.query["region"]? + region ||= env.get("preferences").as(Preferences).region - region = env.params.query["region"]? - region ||= env.get("preferences").as(Preferences).region - - begin - trending, plid = fetch_trending(trending_type, region, locale) - rescue ex - return error_template(500, ex) - end - - templated "feeds/trending" - else - message = translate(locale, "trending_page_disabled") - templated "message" + begin + trending, plid = fetch_trending(trending_type, region, locale) + rescue ex + return error_template(500, ex) end + + templated "feeds/trending" end def self.subscriptions(env) diff --git a/src/invidious/routes/preferences.cr b/src/invidious/routes/preferences.cr index 34cea387..3852f8a9 100644 --- a/src/invidious/routes/preferences.cr +++ b/src/invidious/routes/preferences.cr @@ -200,9 +200,9 @@ module Invidious::Routes::PreferencesRoute CONFIG.default_user_preferences.feed_menu = admin_feed_menu pages_enabled = { - "popular" => (env.params.body["popular_enabled"]?.try &.as(String) || "off") == "on", - "trending" => (env.params.body["trending_enabled"]?.try &.as(String) || "off") == "on", - "search" => (env.params.body["search_enabled"]?.try &.as(String) || "off") == "on", + popular: (env.params.body["popular_enabled"]?.try &.as(String) || "on") == "on", + trending: (env.params.body["trending_enabled"]?.try &.as(String) || "on") == "on", + search: (env.params.body["search_enabled"]?.try &.as(String) || "on") == "on", } CONFIG.pages_enabled = pages_enabled diff --git a/src/invidious/routes/search.cr b/src/invidious/routes/search.cr index 8a9a2d2b..5b10887c 100644 --- a/src/invidious/routes/search.cr +++ b/src/invidious/routes/search.cr @@ -40,12 +40,6 @@ module Invidious::Routes::Search prefs = env.get("preferences").as(Preferences) locale = prefs.locale - # if search is disabled, show the “disabled” message immediately - unless CONFIG.page_enabled?("search") - message = translate(locale, "search_page_disabled") - return templated "message" - end - # otherwise, do a normal search region = env.params.query["region"]? || prefs.region query = Invidious::Search::Query.new(env.params.query, :regular, region)