From e27dd0284af77f8d8d3d5cea1b570e27f6fbaca5 Mon Sep 17 00:00:00 2001 From: Fijxu Date: Thu, 6 Mar 2025 01:43:25 -0300 Subject: [PATCH 1/6] feat: add option to change username --- locales/en-US.json | 8 ++- src/invidious/database/users.cr | 30 +++++++++ src/invidious/routes/account.cr | 69 ++++++++++++++++++++ src/invidious/routing.cr | 2 + src/invidious/views/user/change_username.ecr | 26 ++++++++ src/invidious/views/user/preferences.ecr | 4 ++ 6 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 src/invidious/views/user/change_username.ecr diff --git a/locales/en-US.json b/locales/en-US.json index 4f2c2770..44d4c5ef 100644 --- a/locales/en-US.json +++ b/locales/en-US.json @@ -501,5 +501,11 @@ "toggle_theme": "Toggle Theme", "carousel_slide": "Slide {{current}} of {{total}}", "carousel_skip": "Skip the Carousel", - "carousel_go_to": "Go to slide `x`" + "carousel_go_to": "Go to slide `x`", + "new_username": "New username", + "change_username": "Change username", + "username_required_field": "Username is a required field", + "username_empty": "Username cannot be empty", + "username_is_the_same": "This is your username, use another one", + "username_taken": "Username is already taken, use another one" } diff --git a/src/invidious/database/users.cr b/src/invidious/database/users.cr index 4a3056ea..66a319f9 100644 --- a/src/invidious/database/users.cr +++ b/src/invidious/database/users.cr @@ -184,6 +184,36 @@ module Invidious::Database::Users PG_DB.exec(request, pass, user.email) end + def update_username(user : User, username : String) + request = <<-SQL + UPDATE users + SET email = $1 + WHERE email = $2 + SQL + + PG_DB.exec(request, username, user.email) + end + + def update_user_session_id(user : User, username : String) + request = <<-SQL + UPDATE session_ids + SET email = $1 + WHERE email = $2 + SQL + + PG_DB.exec(request, username, user.email) + end + + def update_user_playlists_author(user : User, username : String) + request = <<-SQL + UPDATE playlists + SET author = $1 + WHERE author = $2 + SQL + + PG_DB.exec(request, username, user.email) + end + # ------------------- # Select # ------------------- diff --git a/src/invidious/routes/account.cr b/src/invidious/routes/account.cr index c8db207c..3164c149 100644 --- a/src/invidious/routes/account.cr +++ b/src/invidious/routes/account.cr @@ -78,6 +78,75 @@ module Invidious::Routes::Account env.redirect referer end + # ------------------- + # Username update + # ------------------- + + # Show the username change interface (GET request) + def get_change_username(env) + locale = env.get("preferences").as(Preferences).locale + + user = env.get? "user" + sid = env.get? "sid" + referer = get_referer(env) + + if !user + return env.redirect referer + end + + user = user.as(User) + sid = sid.as(String) + csrf_token = generate_response(sid, {":change_username"}, HMAC_KEY) + + templated "user/change_username" + end + + # Handle the username change (POST request) + def post_change_username(env) + locale = env.get("preferences").as(Preferences).locale + + user = env.get? "user" + sid = env.get? "sid" + referer = get_referer(env) + + if !user + return env.redirect referer + end + + user = user.as(User) + sid = sid.as(String) + token = env.params.body["csrf_token"]? + + begin + validate_request(token, sid, env.request, HMAC_KEY, locale) + rescue ex + return error_template(400, ex) + end + + new_username = env.params.body["new_username"]? + if new_username.nil? + return error_template(401, "username_required_field") + end + + if new_username.empty? + return error_template(401, "username_empty") + end + + if new_username == user.email + return error_template(401, "username_is_the_same") + end + + if Invidious::Database::Users.select(email: new_username) + return error_template(401, "username_taken") + end + + Invidious::Database::Users.update_username(user, new_username.to_s) + Invidious::Database::Users.update_user_session_id(user, new_username.to_s) + Invidious::Database::Users.update_user_playlists_author(user, new_username.to_s) + + env.redirect referer + end + # ------------------- # Account deletion # ------------------- diff --git a/src/invidious/routing.cr b/src/invidious/routing.cr index 46b71f1f..38ddb839 100644 --- a/src/invidious/routing.cr +++ b/src/invidious/routing.cr @@ -68,6 +68,8 @@ module Invidious::Routing # User account management get "/change_password", Routes::Account, :get_change_password post "/change_password", Routes::Account, :post_change_password + get "/change_username", Routes::Account, :get_change_username + post "/change_username", Routes::Account, :post_change_username get "/delete_account", Routes::Account, :get_delete post "/delete_account", Routes::Account, :post_delete get "/clear_watch_history", Routes::Account, :get_clear_history diff --git a/src/invidious/views/user/change_username.ecr b/src/invidious/views/user/change_username.ecr new file mode 100644 index 00000000..85af79e6 --- /dev/null +++ b/src/invidious/views/user/change_username.ecr @@ -0,0 +1,26 @@ +<% content_for "header" do %> +<%= translate(locale, "change_username") %> - Invidious +<% end %> + +
+
+
+
+
+ <%= translate(locale, "") %> + +
+ + "> + + + + +
+
+
+
+
+
diff --git a/src/invidious/views/user/preferences.ecr b/src/invidious/views/user/preferences.ecr index cf8b5593..5cea8164 100644 --- a/src/invidious/views/user/preferences.ecr +++ b/src/invidious/views/user/preferences.ecr @@ -330,6 +330,10 @@ <%= translate(locale, "Change password") %> +
+ <%= translate(locale, "change_username") %> +
+
<%= translate(locale, "Import/export data") %>
From eff1a101c7f226a375643e7efcef04282dd3868c Mon Sep 17 00:00:00 2001 From: Fijxu Date: Thu, 6 Mar 2025 19:18:13 -0300 Subject: [PATCH 2/6] fix: rename subscriptions materialized view of the user too --- src/invidious/database/users.cr | 7 +++++++ src/invidious/routes/account.cr | 1 + 2 files changed, 8 insertions(+) diff --git a/src/invidious/database/users.cr b/src/invidious/database/users.cr index 66a319f9..bf54a321 100644 --- a/src/invidious/database/users.cr +++ b/src/invidious/database/users.cr @@ -214,6 +214,13 @@ module Invidious::Database::Users PG_DB.exec(request, username, user.email) end + def update_user_materialized_view(user : User, username : String) + view_name = "public.subscriptions_#{sha256(user.email)}" + new_view_name = "subscriptions_#{sha256(username)}" + + PG_DB.exec("ALTER MATERIALIZED VIEW #{view_name} RENAME TO #{new_view_name}") + end + # ------------------- # Select # ------------------- diff --git a/src/invidious/routes/account.cr b/src/invidious/routes/account.cr index 3164c149..b68aefd1 100644 --- a/src/invidious/routes/account.cr +++ b/src/invidious/routes/account.cr @@ -143,6 +143,7 @@ module Invidious::Routes::Account Invidious::Database::Users.update_username(user, new_username.to_s) Invidious::Database::Users.update_user_session_id(user, new_username.to_s) Invidious::Database::Users.update_user_playlists_author(user, new_username.to_s) + Invidious::Database::Users.update_user_materialized_view(user, new_username.to_s) env.redirect referer end From 0c83eb2c39161bfcf2152a4a1cf616b31fb16b95 Mon Sep 17 00:00:00 2001 From: Fijxu Date: Sat, 8 Mar 2025 02:32:39 -0300 Subject: [PATCH 3/6] fix: downcase username and limit username lenght (from routes/login.cr) Users that changed their username to something like `User`, were unable to login because the username is downcased on routes/login.cr --- src/invidious/routes/account.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/invidious/routes/account.cr b/src/invidious/routes/account.cr index b68aefd1..4eff5e1d 100644 --- a/src/invidious/routes/account.cr +++ b/src/invidious/routes/account.cr @@ -123,7 +123,7 @@ module Invidious::Routes::Account return error_template(400, ex) end - new_username = env.params.body["new_username"]? + new_username = env.params.body["new_username"]?.try &.downcase.byte_slice(0, 254) if new_username.nil? return error_template(401, "username_required_field") end From a1a66e064c24faa94d9e8c496f2bb96a502c773e Mon Sep 17 00:00:00 2001 From: Fijxu Date: Wed, 26 Mar 2025 22:39:52 -0300 Subject: [PATCH 4/6] change arg name and prefix locales --- locales/en-US.json | 12 ++++++------ src/invidious/database/users.cr | 4 ++-- src/invidious/routes/account.cr | 8 ++++---- src/invidious/views/user/change_username.ecr | 6 +++--- src/invidious/views/user/preferences.ecr | 2 +- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/locales/en-US.json b/locales/en-US.json index 44d4c5ef..2baf3408 100644 --- a/locales/en-US.json +++ b/locales/en-US.json @@ -502,10 +502,10 @@ "carousel_slide": "Slide {{current}} of {{total}}", "carousel_skip": "Skip the Carousel", "carousel_go_to": "Go to slide `x`", - "new_username": "New username", - "change_username": "Change username", - "username_required_field": "Username is a required field", - "username_empty": "Username cannot be empty", - "username_is_the_same": "This is your username, use another one", - "username_taken": "Username is already taken, use another one" + "accounts_new_username": "New username", + "accounts_change_username": "Change username", + "accounts_username_required_field": "Username is a required field", + "accounts_username_empty": "Username cannot be empty", + "accounts_username_is_the_same": "This is your username, use another one", + "accounts_username_taken": "Username is already taken, use another one" } diff --git a/src/invidious/database/users.cr b/src/invidious/database/users.cr index bf54a321..a750bc5e 100644 --- a/src/invidious/database/users.cr +++ b/src/invidious/database/users.cr @@ -184,14 +184,14 @@ module Invidious::Database::Users PG_DB.exec(request, pass, user.email) end - def update_username(user : User, username : String) + def update_username(user : User, new_username : String) request = <<-SQL UPDATE users SET email = $1 WHERE email = $2 SQL - PG_DB.exec(request, username, user.email) + PG_DB.exec(request, new_username, user.email) end def update_user_session_id(user : User, username : String) diff --git a/src/invidious/routes/account.cr b/src/invidious/routes/account.cr index 4eff5e1d..647e594c 100644 --- a/src/invidious/routes/account.cr +++ b/src/invidious/routes/account.cr @@ -125,19 +125,19 @@ module Invidious::Routes::Account new_username = env.params.body["new_username"]?.try &.downcase.byte_slice(0, 254) if new_username.nil? - return error_template(401, "username_required_field") + return error_template(401, "accounts_username_required_field") end if new_username.empty? - return error_template(401, "username_empty") + return error_template(401, "accounts_username_empty") end if new_username == user.email - return error_template(401, "username_is_the_same") + return error_template(401, "accounts_username_is_the_same") end if Invidious::Database::Users.select(email: new_username) - return error_template(401, "username_taken") + return error_template(401, "accounts_username_taken") end Invidious::Database::Users.update_username(user, new_username.to_s) diff --git a/src/invidious/views/user/change_username.ecr b/src/invidious/views/user/change_username.ecr index 85af79e6..ed7d4cc1 100644 --- a/src/invidious/views/user/change_username.ecr +++ b/src/invidious/views/user/change_username.ecr @@ -1,5 +1,5 @@ <% content_for "header" do %> -<%= translate(locale, "change_username") %> - Invidious +<%= translate(locale, "accounts_change_username") %> - Invidious <% end %>
@@ -10,11 +10,11 @@ <%= translate(locale, "") %>
- + "> diff --git a/src/invidious/views/user/preferences.ecr b/src/invidious/views/user/preferences.ecr index 5cea8164..d88177ca 100644 --- a/src/invidious/views/user/preferences.ecr +++ b/src/invidious/views/user/preferences.ecr @@ -331,7 +331,7 @@
From deb342b3e6faaee9da5ac3ff115706b72164a413 Mon Sep 17 00:00:00 2001 From: Fijxu Date: Wed, 26 Mar 2025 22:42:25 -0300 Subject: [PATCH 5/6] fix wrong translation --- src/invidious/views/user/change_username.ecr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/invidious/views/user/change_username.ecr b/src/invidious/views/user/change_username.ecr index ed7d4cc1..d4c4100e 100644 --- a/src/invidious/views/user/change_username.ecr +++ b/src/invidious/views/user/change_username.ecr @@ -10,7 +10,7 @@ <%= translate(locale, "") %>
- + ">