From e27dd0284af77f8d8d3d5cea1b570e27f6fbaca5 Mon Sep 17 00:00:00 2001 From: Fijxu Date: Thu, 6 Mar 2025 01:43:25 -0300 Subject: [PATCH] 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") %>