mirror of
				https://github.com/iv-org/invidious.git
				synced 2025-10-31 12:42:09 +00:00 
			
		
		
		
	Move DB queries related to session tokens in a separate module
This commit is contained in:
		| @@ -247,7 +247,7 @@ before_all do |env| | ||||
|  | ||||
|     # Invidious users only have SID | ||||
|     if !env.request.cookies.has_key? "SSID" | ||||
|       if email = PG_DB.query_one?("SELECT email FROM session_ids WHERE id = $1", sid, as: String) | ||||
|       if email = Invidious::Database::SessionIDs.select_email(sid) | ||||
|         user = PG_DB.query_one("SELECT * FROM users WHERE email = $1", email, as: User) | ||||
|         csrf_token = generate_response(sid, { | ||||
|           ":authorize_token", | ||||
| @@ -633,6 +633,7 @@ get "/subscription_manager" do |env| | ||||
|   end | ||||
|  | ||||
|   user = user.as(User) | ||||
|   sid = sid.as(String) | ||||
|  | ||||
|   if !user.password | ||||
|     # Refresh account | ||||
| @@ -1008,7 +1009,7 @@ post "/delete_account" do |env| | ||||
|  | ||||
|   view_name = "subscriptions_#{sha256(user.email)}" | ||||
|   PG_DB.exec("DELETE FROM users * WHERE email = $1", user.email) | ||||
|   PG_DB.exec("DELETE FROM session_ids * WHERE email = $1", user.email) | ||||
|   Invidious::Database::SessionIDs.delete(email: user.email) | ||||
|   PG_DB.exec("DROP MATERIALIZED VIEW #{view_name}") | ||||
|  | ||||
|   env.request.cookies.each do |cookie| | ||||
| @@ -1150,8 +1151,7 @@ get "/token_manager" do |env| | ||||
|   end | ||||
|  | ||||
|   user = user.as(User) | ||||
|  | ||||
|   tokens = PG_DB.query_all("SELECT id, issued FROM session_ids WHERE email = $1 ORDER BY issued DESC", user.email, as: {session: String, issued: Time}) | ||||
|   tokens = Invidious::Database::SessionIDs.select_all(user.email) | ||||
|  | ||||
|   templated "token_manager" | ||||
| end | ||||
| @@ -1200,7 +1200,7 @@ post "/token_ajax" do |env| | ||||
|  | ||||
|   case action | ||||
|   when .starts_with? "action_revoke_token" | ||||
|     PG_DB.exec("DELETE FROM session_ids * WHERE id = $1 AND email = $2", session, user.email) | ||||
|     Invidious::Database::SessionIDs.delete(sid: session, email: user.email) | ||||
|   else | ||||
|     next error_json(400, "Unsupported action #{action}") | ||||
|   end | ||||
|   | ||||
							
								
								
									
										46
									
								
								src/invidious/database/nonces.cr
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/invidious/database/nonces.cr
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | ||||
| require "./base.cr" | ||||
|  | ||||
| module Invidious::Database::Nonces | ||||
|   extend self | ||||
|  | ||||
|   # ------------------- | ||||
|   #  Insert | ||||
|   # ------------------- | ||||
|  | ||||
|   def insert(nonce : String, expire : Time) | ||||
|     request = <<-SQL | ||||
|       INSERT INTO nonces | ||||
|       VALUES ($1, $2) | ||||
|       ON CONFLICT DO NOTHING | ||||
|     SQL | ||||
|  | ||||
|     PG_DB.exec(request, nonce, expire) | ||||
|   end | ||||
|  | ||||
|   # ------------------- | ||||
|   #  Update | ||||
|   # ------------------- | ||||
|  | ||||
|   def update_set_expired(nonce : String) | ||||
|     request = <<-SQL | ||||
|       UPDATE nonces | ||||
|       SET expire = $1 | ||||
|       WHERE nonce = $2 | ||||
|     SQL | ||||
|  | ||||
|     PG_DB.exec(request, Time.utc(1990, 1, 1), nonce) | ||||
|   end | ||||
|  | ||||
|   # ------------------- | ||||
|   #  Select | ||||
|   # ------------------- | ||||
|  | ||||
|   def select(nonce : String) : Tuple(String, Time)? | ||||
|     request = <<-SQL | ||||
|       SELECT * FROM nonces | ||||
|       WHERE nonce = $1 | ||||
|     SQL | ||||
|  | ||||
|     return PG_DB.query_one?(request, nonce, as: {String, Time}) | ||||
|   end | ||||
| end | ||||
							
								
								
									
										74
									
								
								src/invidious/database/sessions.cr
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								src/invidious/database/sessions.cr
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,74 @@ | ||||
| require "./base.cr" | ||||
|  | ||||
| module Invidious::Database::SessionIDs | ||||
|   extend self | ||||
|  | ||||
|   # ------------------- | ||||
|   #  Insert | ||||
|   # ------------------- | ||||
|  | ||||
|   def insert(sid : String, email : String, handle_conflicts : Bool = false) | ||||
|     request = <<-SQL | ||||
|       INSERT INTO session_ids | ||||
|       VALUES ($1, $2, $3) | ||||
|     SQL | ||||
|  | ||||
|     request += " ON CONFLICT (id) DO NOTHING" if handle_conflicts | ||||
|  | ||||
|     PG_DB.exec(request, sid, email, Time.utc) | ||||
|   end | ||||
|  | ||||
|   # ------------------- | ||||
|   #  Delete | ||||
|   # ------------------- | ||||
|  | ||||
|   def delete(*, sid : String) | ||||
|     request = <<-SQL | ||||
|       DELETE FROM session_ids * | ||||
|       WHERE id = $1 | ||||
|     SQL | ||||
|  | ||||
|     PG_DB.exec(request, sid) | ||||
|   end | ||||
|  | ||||
|   def delete(*, email : String) | ||||
|     request = <<-SQL | ||||
|       DELETE FROM session_ids * | ||||
|       WHERE email = $1 | ||||
|     SQL | ||||
|  | ||||
|     PG_DB.exec(request, email) | ||||
|   end | ||||
|  | ||||
|   def delete(*, sid : String, email : String) | ||||
|     request = <<-SQL | ||||
|       DELETE FROM session_ids * | ||||
|       WHERE id = $1 AND email = $2 | ||||
|     SQL | ||||
|  | ||||
|     PG_DB.exec(request, sid, email) | ||||
|   end | ||||
|  | ||||
|   # ------------------- | ||||
|   #  Select | ||||
|   # ------------------- | ||||
|  | ||||
|   def select_email(sid : String) : String? | ||||
|     request = <<-SQL | ||||
|       SELECT email FROM session_ids | ||||
|       WHERE id = $1 | ||||
|     SQL | ||||
|  | ||||
|     PG_DB.query_one?(request, sid, as: String) | ||||
|   end | ||||
|  | ||||
|   def select_all(email : String) : Array({session: String, issued: Time}) | ||||
|     request = <<-SQL | ||||
|       SELECT id, issued FROM session_ids | ||||
|       WHERE email = $1 | ||||
|       ORDER BY issued DESC | ||||
|     SQL | ||||
|  | ||||
|     PG_DB.query_all(request, email, as: {session: String, issued: Time}) | ||||
|   end | ||||
| end | ||||
| @@ -99,7 +99,7 @@ class AuthHandler < Kemal::Handler | ||||
|         session = URI.decode_www_form(token["session"].as_s) | ||||
|         scopes, expire, signature = validate_request(token, session, env.request, HMAC_KEY, PG_DB, nil) | ||||
|  | ||||
|         if email = PG_DB.query_one?("SELECT email FROM session_ids WHERE id = $1", session, as: String) | ||||
|         if email = Invidious::Database::SessionIDs.select_email(session) | ||||
|           user = PG_DB.query_one("SELECT * FROM users WHERE email = $1", email, as: User) | ||||
|         end | ||||
|       elsif sid = env.request.cookies["SID"]?.try &.value | ||||
| @@ -107,7 +107,7 @@ class AuthHandler < Kemal::Handler | ||||
|           raise "Cannot use token as SID" | ||||
|         end | ||||
|  | ||||
|         if email = PG_DB.query_one?("SELECT email FROM session_ids WHERE id = $1", sid, as: String) | ||||
|         if email = Invidious::Database::SessionIDs.select_email(sid) | ||||
|           user = PG_DB.query_one("SELECT * FROM users WHERE email = $1", email, as: User) | ||||
|         end | ||||
|  | ||||
|   | ||||
| @@ -2,7 +2,7 @@ require "crypto/subtle" | ||||
|  | ||||
| def generate_token(email, scopes, expire, key, db) | ||||
|   session = "v1:#{Base64.urlsafe_encode(Random::Secure.random_bytes(32))}" | ||||
|   PG_DB.exec("INSERT INTO session_ids VALUES ($1, $2, $3)", session, email, Time.utc) | ||||
|   Invidious::Database::SessionIDs.insert(session, email) | ||||
|  | ||||
|   token = { | ||||
|     "session" => session, | ||||
| @@ -30,7 +30,7 @@ def generate_response(session, scopes, key, db, expire = 6.hours, use_nonce = fa | ||||
|  | ||||
|   if use_nonce | ||||
|     nonce = Random::Secure.hex(16) | ||||
|     db.exec("INSERT INTO nonces VALUES ($1, $2) ON CONFLICT DO NOTHING", nonce, expire) | ||||
|     Invidious::Database::Nonces.insert(nonce, expire) | ||||
|     token["nonce"] = nonce | ||||
|   end | ||||
|  | ||||
| @@ -92,9 +92,9 @@ def validate_request(token, session, request, key, db, locale = nil) | ||||
|     raise InfoException.new("Invalid signature") | ||||
|   end | ||||
|  | ||||
|   if token["nonce"]? && (nonce = db.query_one?("SELECT * FROM nonces WHERE nonce = $1", token["nonce"], as: {String, Time})) | ||||
|   if token["nonce"]? && (nonce = Invidious::Database::Nonces.select(token["nonce"].as_s)) | ||||
|     if nonce[1] > Time.utc | ||||
|       db.exec("UPDATE nonces SET expire = $1 WHERE nonce = $2", Time.utc(1990, 1, 1), nonce[0]) | ||||
|       Invidious::Database::Nonces.update_set_expired(nonce[0]) | ||||
|     else | ||||
|       raise InfoException.new("Erroneous token") | ||||
|     end | ||||
|   | ||||
| @@ -312,7 +312,7 @@ module Invidious::Routes::API::V1::Authenticated | ||||
|     user = env.get("user").as(User) | ||||
|     scopes = env.get("scopes").as(Array(String)) | ||||
|  | ||||
|     tokens = PG_DB.query_all("SELECT id, issued FROM session_ids WHERE email = $1", user.email, as: {session: String, issued: Time}) | ||||
|     tokens = Invidious::Database::SessionIDs.select_all(user.email) | ||||
|  | ||||
|     JSON.build do |json| | ||||
|       json.array do | ||||
| @@ -400,9 +400,9 @@ module Invidious::Routes::API::V1::Authenticated | ||||
|  | ||||
|     # Allow tokens to revoke other tokens with correct scope | ||||
|     if session == env.get("session").as(String) | ||||
|       PG_DB.exec("DELETE FROM session_ids * WHERE id = $1", session) | ||||
|       Invidious::Database::SessionIDs.delete(sid: session) | ||||
|     elsif scopes_include_scope(scopes, "GET:tokens") | ||||
|       PG_DB.exec("DELETE FROM session_ids * WHERE id = $1", session) | ||||
|       Invidious::Database::SessionIDs.delete(sid: session) | ||||
|     else | ||||
|       return error_json(400, "Cannot revoke session #{session}") | ||||
|     end | ||||
|   | ||||
| @@ -336,7 +336,7 @@ module Invidious::Routes::Login | ||||
|  | ||||
|         if Crypto::Bcrypt::Password.new(user.password.not_nil!).verify(password.byte_slice(0, 55)) | ||||
|           sid = Base64.urlsafe_encode(Random::Secure.random_bytes(32)) | ||||
|           PG_DB.exec("INSERT INTO session_ids VALUES ($1, $2, $3)", sid, email, Time.utc) | ||||
|           Invidious::Database::SessionIDs.insert(sid, email) | ||||
|  | ||||
|           if Kemal.config.ssl || CONFIG.https_only | ||||
|             secure = true | ||||
| @@ -455,7 +455,7 @@ module Invidious::Routes::Login | ||||
|         args = arg_array(user_array) | ||||
|  | ||||
|         PG_DB.exec("INSERT INTO users VALUES (#{args})", args: user_array) | ||||
|         PG_DB.exec("INSERT INTO session_ids VALUES ($1, $2, $3)", sid, email, Time.utc) | ||||
|         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)}") | ||||
| @@ -511,7 +511,7 @@ module Invidious::Routes::Login | ||||
|       return error_template(400, ex) | ||||
|     end | ||||
|  | ||||
|     PG_DB.exec("DELETE FROM session_ids * WHERE id = $1", sid) | ||||
|     Invidious::Database::SessionIDs.delete(sid: sid) | ||||
|  | ||||
|     env.request.cookies.each do |cookie| | ||||
|       cookie.expires = Time.utc(1990, 1, 1) | ||||
|   | ||||
| @@ -30,7 +30,7 @@ struct User | ||||
| end | ||||
|  | ||||
| def get_user(sid, headers, db, refresh = true) | ||||
|   if email = db.query_one?("SELECT email FROM session_ids WHERE id = $1", sid, as: String) | ||||
|   if email = Invidious::Database::SessionIDs.select_email(sid) | ||||
|     user = db.query_one("SELECT * FROM users WHERE email = $1", email, as: User) | ||||
|  | ||||
|     if refresh && Time.utc - user.updated > 1.minute | ||||
| @@ -42,8 +42,7 @@ def get_user(sid, headers, db, refresh = true) | ||||
|       db.exec("INSERT INTO users VALUES (#{args}) \ | ||||
|       ON CONFLICT (email) DO UPDATE SET updated = $1, subscriptions = $3", args: user_array) | ||||
|  | ||||
|       db.exec("INSERT INTO session_ids VALUES ($1,$2,$3) \ | ||||
|       ON CONFLICT (id) DO NOTHING", sid, user.email, Time.utc) | ||||
|       Invidious::Database::SessionIDs.insert(sid, user.email, handle_conflicts: true) | ||||
|  | ||||
|       begin | ||||
|         view_name = "subscriptions_#{sha256(user.email)}" | ||||
| @@ -60,8 +59,7 @@ def get_user(sid, headers, db, refresh = true) | ||||
|     db.exec("INSERT INTO users VALUES (#{args}) \ | ||||
|     ON CONFLICT (email) DO UPDATE SET updated = $1, subscriptions = $3", args: user_array) | ||||
|  | ||||
|     db.exec("INSERT INTO session_ids VALUES ($1,$2,$3) \ | ||||
|     ON CONFLICT (id) DO NOTHING", sid, user.email, Time.utc) | ||||
|     Invidious::Database::SessionIDs.insert(sid, user.email, handle_conflicts: true) | ||||
|  | ||||
|     begin | ||||
|       view_name = "subscriptions_#{sha256(user.email)}" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Samantaz Fox
					Samantaz Fox