From 71a55692513f14e4c47afd86995a0e4a33a8defa Mon Sep 17 00:00:00 2001 From: Fijxu Date: Sat, 24 Jan 2026 22:16:40 -0300 Subject: [PATCH] Set current companion using preferences and not a separate cookie --- config/config.example.yml | 9 ------ src/invidious/config.cr | 4 +-- src/invidious/routes/backend_switcher.cr | 17 ++++++++--- src/invidious/routes/before_all.cr | 39 +++++++++++++++--------- src/invidious/routes/preferences.cr | 2 +- src/invidious/user/cookies.cr | 26 ++-------------- src/invidious/user/preferences.cr | 1 + src/invidious/views/template.ecr | 8 ++--- 8 files changed, 48 insertions(+), 58 deletions(-) diff --git a/config/config.example.yml b/config/config.example.yml index c7a7e1e8..cd92b55d 100644 --- a/config/config.example.yml +++ b/config/config.example.yml @@ -1163,15 +1163,6 @@ video_cache: ## #max_dash_resolution: null -## -## The name of the cookie to hold the backend id that -## the client is using. -## -## Accepted values: a string -## Default: "COMPANION_ID" -## -#server_id_cookie_name: "COMPANION_ID" - ## ## Checks if the companions in the `invidious_companion` list ## are alive using their `/healthz` endpoint. diff --git a/src/invidious/config.cr b/src/invidious/config.cr index b477b19c..4bc11fb2 100644 --- a/src/invidious/config.cr +++ b/src/invidious/config.cr @@ -60,6 +60,8 @@ struct ConfigPreferences @[YAML::Field(ignore: true)] property default_trending_type : Invidious::Routes::Feeds::TrendingTypes = Invidious::Routes::Feeds::TrendingTypes::Default property show_community_backends : Bool = false + @[YAML::Field(ignore: true)] + property current_companion : Int32? = nil def to_tuple {% begin %} @@ -223,8 +225,6 @@ class Config property pubsub_domain : String = "" - property server_id_cookie_name : String = "COMPANION_ID" - property video_cache : VideoCacheConfig = VideoCacheConfig.from_yaml("") class VideoCacheConfig diff --git a/src/invidious/routes/backend_switcher.cr b/src/invidious/routes/backend_switcher.cr index e4702729..7d143e39 100644 --- a/src/invidious/routes/backend_switcher.cr +++ b/src/invidious/routes/backend_switcher.cr @@ -3,13 +3,22 @@ module Invidious::Routes::BackendSwitcher def self.switch(env) referer = get_referer(env, unroll: false) - backend_id = env.params.query["backend_id"]?.try &.to_i + companion_id = env.params.query["companion_id"]?.try &.to_i + preferences = env.get("preferences").as(Preferences) + user = env.get? "user" - if backend_id.nil? - return error_template(400, "Backend ID is required") + if companion_id.nil? + return error_template(400, "Companion ID is required") end - env.response.cookies[CONFIG.server_id_cookie_name] = Invidious::User::Cookies.server_id(env.request.headers["Host"], backend_id) + if user + user = user.as(User) + user.preferences.current_companion = companion_id + Invidious::Database::Users.update_preferences(user) + else + preferences.current_companion = companion_id + env.response.cookies["PREFS"] = Invidious::User::Cookies.prefs(env.request.headers["Host"], preferences) + end env.redirect referer end diff --git a/src/invidious/routes/before_all.cr b/src/invidious/routes/before_all.cr index 2082eb72..297b7ce0 100644 --- a/src/invidious/routes/before_all.cr +++ b/src/invidious/routes/before_all.cr @@ -169,7 +169,6 @@ module Invidious::Routes::BeforeAll::Companion companion_status : CompanionStatus, preferences : Preferences, ) - cookie_name = CONFIG.server_id_cookie_name c_size = CONFIG.invidious_companion.size current_companion = 0 @@ -181,20 +180,20 @@ module Invidious::Routes::BeforeAll::Companion current_companion = index else # Set cookie if there is no cookie - if !env.request.cookies.has_key?(cookie_name) + if !env.request.cookies.has_key?("PREFS") current_companion = self.find_available_companion(env, host, nil, companion_status, preferences) if current_companion - self.set_cookie(env, host, current_companion) + self.set_companion(env, preferences, host, current_companion) else return "" end else begin - current_companion = get_cookie(env) + current_companion = get_companion(preferences) current_companion = self.find_available_companion(env, host, current_companion, companion_status, preferences) rescue current_companion = rand(c_size) - self.set_cookie(env, host, current_companion) + self.set_companion(env, preferences, host, current_companion) end end @@ -219,18 +218,29 @@ module Invidious::Routes::BeforeAll::Companion return companion_csp end - private def set_cookie( + private def set_companion( env : HTTP::Server::Context, + preferences : Preferences, host : String, current_companion : Int32, ) - cookie_name = CONFIG.server_id_cookie_name - env.response.cookies[cookie_name] = Invidious::User::Cookies.server_id(host, current_companion) + user = env.get? "user" + + if user + user = user.as(User) + user.preferences.current_companion = current_companion + Invidious::Database::Users.update_preferences(user) + else + preferences.current_companion = current_companion + env.set "preferences", preferences + env.response.cookies["PREFS"] = Invidious::User::Cookies.prefs(env.request.headers["Host"], preferences) + end end - private def get_cookie(env : HTTP::Server::Context) - cookie_name = CONFIG.server_id_cookie_name - return env.request.cookies[cookie_name].value.try &.to_i + private def get_companion( + preferences : Preferences, + ) + return preferences.current_companion end private def find_available_companion( @@ -260,7 +270,7 @@ module Invidious::Routes::BeforeAll::Companion end end - current_companion = self.wrap_current_companion(env, host, current_companion, c_size, working_companions) + current_companion = self.wrap_current_companion(env, host, current_companion, c_size, working_companions, preferences) if current_companion.nil? return nil end @@ -271,7 +281,7 @@ module Invidious::Routes::BeforeAll::Companion if alive_companion current_companion = alive_companion env.set "companion_switched", true - self.set_cookie(env, host, current_companion) + self.set_companion(env, preferences, host, current_companion) end end @@ -294,11 +304,12 @@ module Invidious::Routes::BeforeAll::Companion current_companion : Int32, invidious_companion_size : Int32, working_companions : Array(Int32), + preferences : Preferences, ) if (current_companion < 0) || current_companion >= invidious_companion_size current_companion = self.get_available_companion(invidious_companion_size, working_companions) if current_companion - self.set_cookie(env, host, current_companion) + self.set_companion(env, preferences, host, current_companion) else current_companion = rand(invidious_companion_size) end diff --git a/src/invidious/routes/preferences.cr b/src/invidious/routes/preferences.cr index e42b68bc..55ffaff6 100644 --- a/src/invidious/routes/preferences.cr +++ b/src/invidious/routes/preferences.cr @@ -174,7 +174,7 @@ module Invidious::Routes::PreferencesRoute show_community_backends = env.params.body["show_community_backends"]?.try &.as(String) show_community_backends ||= "off" - show_community_backends= show_community_backends == "on" + show_community_backends = show_community_backends == "on" # Convert to JSON and back again to take advantage of converters used for compatibility preferences = Preferences.from_json({ diff --git a/src/invidious/user/cookies.cr b/src/invidious/user/cookies.cr index 605ead3a..37c64a5c 100644 --- a/src/invidious/user/cookies.cr +++ b/src/invidious/user/cookies.cr @@ -50,30 +50,8 @@ struct Invidious::User expires: Time.utc + 2.years, secure: @@secure, http_only: false, - samesite: HTTP::Cookie::SameSite::Lax - ) - end - - # Backend (CONFIG.server_id_cookie_name) cookie - # Parameter "domain" comes from the global config - def server_id(domain : String?, server_id : Int32) : HTTP::Cookie - # Strip the port from the domain if it's being accessed from another port - # Browsers will reject the cookie if it contains the port number. This is - # because `example.com:3000` is not the same as `example.com` on a cookie. - domain = domain.split(":")[0] - # Not secure if it's being accessed from I2P - # Browsers expect the domain to include https. On I2P there is no HTTPS - if domain.not_nil!.split(".").last == "i2p" - @@secure = false - end - return HTTP::Cookie.new( - name: CONFIG.server_id_cookie_name, - domain: domain, - path: "/", - value: server_id.to_s, - secure: @@secure, - http_only: true, - samesite: HTTP::Cookie::SameSite::Lax + samesite: HTTP::Cookie::SameSite::Lax, + path: "/" ) end end diff --git a/src/invidious/user/preferences.cr b/src/invidious/user/preferences.cr index 112200f8..c82f3712 100644 --- a/src/invidious/user/preferences.cr +++ b/src/invidious/user/preferences.cr @@ -60,6 +60,7 @@ struct Preferences property default_trending_type : Invidious::Routes::Feeds::TrendingTypes = Invidious::Routes::Feeds::TrendingTypes::Default property default_playlist : String? = nil property show_community_backends : Bool = false + property current_companion : Int32? = nil module BoolToString def self.to_json(value : String, json : JSON::Builder) diff --git a/src/invidious/views/template.ecr b/src/invidious/views/template.ecr index 2364d06e..ebcf6dc2 100644 --- a/src/invidious/views/template.ecr +++ b/src/invidious/views/template.ecr @@ -146,7 +146,7 @@ next if companion.i2p_public_url.host.nil? && using_i2p backend_name_prefix = CONFIG.backend_name_prefix + (index + 1).to_s %> - display: inline-block;"> + display: inline-block;"> <%= HTML.escape(backend_name_prefix) %> <%= HTML.escape(companion.note) %>

<% end %> - +
<% if CONFIG.instance_maintainer_email || CONFIG.modified_source_code_url || CONFIG.footer_instance_tos_link || CONFIG.footer_instance_privacy_policy_link %>