From 72ec494f2bbd63b481242817fdd6c53f00b9dca3 Mon Sep 17 00:00:00 2001 From: syeopite Date: Wed, 26 Jul 2023 07:39:50 -0700 Subject: [PATCH] Extract logic for registration into #signups --- src/invidious/routes/login.cr | 216 ++++++++++++++++++---------------- 1 file changed, 115 insertions(+), 101 deletions(-) diff --git a/src/invidious/routes/login.cr b/src/invidious/routes/login.cr index d0f7ac22..071dd035 100644 --- a/src/invidious/routes/login.cr +++ b/src/invidious/routes/login.cr @@ -72,107 +72,7 @@ module Invidious::Routes::Login env.response.cookies << cookie end else - if !CONFIG.registration_enabled - return error_template(400, "Registration has been disabled by administrator.") - end - - if password.empty? - return error_template(401, "Password cannot be empty") - end - - # See https://security.stackexchange.com/a/39851 - if password.bytesize > 55 - return error_template(400, "Password cannot be longer than 55 characters") - end - - password = password.byte_slice(0, 55) - - if CONFIG.captcha_enabled - captcha_type = env.params.body["captcha_type"]? - answer = env.params.body["answer"]? - change_type = env.params.body["change_type"]? - - if !captcha_type || change_type - if change_type - captcha_type = change_type - end - captcha_type ||= "image" - - account_type = "invidious" - - if captcha_type == "image" - captcha = Invidious::User::Captcha.generate_image(HMAC_KEY) - else - captcha = Invidious::User::Captcha.generate_text(HMAC_KEY) - end - - return templated "user/login" - end - - tokens = env.params.body.select { |k, _| k.match(/^token\[\d+\]$/) }.map { |_, v| v } - - answer ||= "" - captcha_type ||= "image" - - case captcha_type - when "image" - answer = answer.lstrip('0') - answer = OpenSSL::HMAC.hexdigest(:sha256, HMAC_KEY, answer) - - begin - validate_request(tokens[0], answer, env.request, HMAC_KEY, locale) - rescue ex - return error_template(400, ex) - end - else # "text" - answer = Digest::MD5.hexdigest(answer.downcase.strip) - - if tokens.empty? - return error_template(500, "Erroneous CAPTCHA") - end - - found_valid_captcha = false - error_exception = Exception.new - tokens.each do |tok| - begin - validate_request(tok, answer, env.request, HMAC_KEY, locale) - found_valid_captcha = true - rescue ex - error_exception = ex - end - end - - if !found_valid_captcha - return error_template(500, error_exception) - end - end - end - - sid = Base64.urlsafe_encode(Random::Secure.random_bytes(32)) - user, sid = create_user(sid, email, password) - - if language_header = env.request.headers["Accept-Language"]? - if language = ANG.language_negotiator.best(language_header, LOCALES.keys) - user.preferences.locale = language.header - end - end - - Invidious::Database::Users.insert(user) - Invidious::Database::SessionIDs.insert(sid, email) - - view_name = "subscriptions_#{sha256(user.email)}" - PG_DB.exec("CREATE MATERIALIZED VIEW #{view_name} AS #{MATERIALIZED_VIEW_SQL.call(user.email)}") - - env.response.cookies["SID"] = Invidious::User::Cookies.sid(CONFIG.domain, sid) - - if env.request.cookies["PREFS"]? - user.preferences = env.get("preferences").as(Preferences) - Invidious::Database::Users.update_preferences(user) - - cookie = env.request.cookies["PREFS"] - cookie.expires = Time.utc(1990, 1, 1) - env.response.cookies << cookie - end + return self.signup(env) end env.redirect referer @@ -181,6 +81,120 @@ module Invidious::Routes::Login end end + def self.signup(env) + locale = env.get("preferences").as(Preferences).locale + referer = get_referer(env, "/feed/subscriptions") + + if !CONFIG.registration_enabled + return error_template(400, "Registration has been disabled by administrator.") + end + + email = env.params.body["email"]?.try &.downcase.byte_slice(0, 254) + password = env.params.body["password"]? + + if password.nil? || password.empty? + return error_template(401, "Password cannot be empty") + end + + if email.nil? || email.empty? + return error_template(401, "User ID is a required field") + end + + # See https://security.stackexchange.com/a/39851 + if password.bytesize > 55 + return error_template(400, "Password cannot be longer than 55 characters") + end + + password = password.byte_slice(0, 55) + + if CONFIG.captcha_enabled + captcha_type = env.params.body["captcha_type"]? + answer = env.params.body["answer"]? + change_type = env.params.body["change_type"]? + + if !captcha_type || change_type + if change_type + captcha_type = change_type + end + captcha_type ||= "image" + + account_type = "invidious" + + if captcha_type == "image" + captcha = Invidious::User::Captcha.generate_image(HMAC_KEY) + else + captcha = Invidious::User::Captcha.generate_text(HMAC_KEY) + end + + return templated "user/login" + end + + tokens = env.params.body.select { |k, _| k.match(/^token\[\d+\]$/) }.map { |_, v| v } + + answer ||= "" + captcha_type ||= "image" + + case captcha_type + when "image" + answer = answer.lstrip('0') + answer = OpenSSL::HMAC.hexdigest(:sha256, HMAC_KEY, answer) + + begin + validate_request(tokens[0], answer, env.request, HMAC_KEY, locale) + rescue ex + return error_template(400, ex) + end + else # "text" + answer = Digest::MD5.hexdigest(answer) + + if tokens.empty? + return error_template(500, "Erroneous CAPTCHA") + end + + found_valid_captcha = false + error_exception = Exception.new + tokens.each do |tok| + begin + validate_request(tok, answer, env.request, HMAC_KEY, locale) + found_valid_captcha = true + rescue ex + error_exception = ex + end + end + + if !found_valid_captcha + return error_template(500, error_exception) + end + end + end + + sid = Base64.urlsafe_encode(Random::Secure.random_bytes(32)) + user, sid = create_user(sid, email, password) + + if language_header = env.request.headers["Accept-Language"]? + if language = ANG.language_negotiator.best(language_header, LOCALES.keys) + user.preferences.locale = language.header + end + end + + Invidious::Database::Users.insert(user) + Invidious::Database::SessionIDs.insert(sid, email) + + view_name = "subscriptions_#{sha256(user.email)}" + PG_DB.exec("CREATE MATERIALIZED VIEW #{view_name} AS #{MATERIALIZED_VIEW_SQL.call(user.email)}") + + env.response.cookies["SID"] = Invidious::User::Cookies.sid(CONFIG.domain, sid) + + if env.request.cookies["PREFS"]? + user.preferences = env.get("preferences").as(Preferences) + Invidious::Database::Users.update_preferences(user) + + cookie = env.request.cookies["PREFS"] + cookie.expires = Time.utc(1990, 1, 1) + env.response.cookies << cookie + end + end + def self.signout(env) locale = env.get("preferences").as(Preferences).locale