@@ -38,14 +38,13 @@ require "./invidious/jobs/**"
3838CONFIG = Config .load
3939HMAC_KEY = CONFIG .hmac_key || Random ::Secure .hex(32 )
4040
41- PG_DB = DB .open CONFIG .database_url
42- ARCHIVE_URL = URI .parse(" https://archive.org" )
43- LOGIN_URL = URI .parse(" https://accounts.google.com" )
44- PUBSUB_URL = URI .parse(" https://pubsubhubbub.appspot.com" )
45- REDDIT_URL = URI .parse(" https://www.reddit.com" )
46- TEXTCAPTCHA_URL = URI .parse(" https://textcaptcha.com" )
47- YT_URL = URI .parse(" https://www.youtube.com" )
48- HOST_URL = make_host_url(Kemal .config)
41+ PG_DB = DB .open CONFIG .database_url
42+ ARCHIVE_URL = URI .parse(" https://archive.org" )
43+ LOGIN_URL = URI .parse(" https://accounts.google.com" )
44+ PUBSUB_URL = URI .parse(" https://pubsubhubbub.appspot.com" )
45+ REDDIT_URL = URI .parse(" https://www.reddit.com" )
46+ YT_URL = URI .parse(" https://www.youtube.com" )
47+ HOST_URL = make_host_url(Kemal .config)
4948
5049CHARS_SAFE = " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
5150TEST_IDS = {" AgbeGFYluEA" , " BaW_jenozKc" , " a9LDPn-MO4I" , " ddFvjfvPnqk" , " iqKdEhx-dD4" }
366365 Invidious ::Routing .get " /results" , Invidious ::Routes ::Search , :results
367366 Invidious ::Routing .get " /search" , Invidious ::Routes ::Search , :search
368367
369- Invidious ::Routing .get " /login" , Invidious ::Routes ::Login , :login_page
370- Invidious ::Routing .post " /login" , Invidious ::Routes ::Login , :login
371- Invidious ::Routing .post " /signout" , Invidious ::Routes ::Login , :signout
372-
373- Invidious ::Routing .get " /preferences" , Invidious ::Routes ::PreferencesRoute , :show
374- Invidious ::Routing .post " /preferences" , Invidious ::Routes ::PreferencesRoute , :update
375- Invidious ::Routing .get " /toggle_theme" , Invidious ::Routes ::PreferencesRoute , :toggle_theme
376- Invidious ::Routing .get " /data_control" , Invidious ::Routes ::PreferencesRoute , :data_control
377- Invidious ::Routing .post " /data_control" , Invidious ::Routes ::PreferencesRoute , :update_data_control
368+ # User routes
369+ define_user_routes()
378370
379371 # Feeds
380372 Invidious ::Routing .get " /view_all_playlists" , Invidious ::Routes ::Feeds , :view_all_playlists_redirect
@@ -414,325 +406,6 @@ define_v1_api_routes()
414406define_api_manifest_routes()
415407define_video_playback_routes()
416408
417- get " /change_password" do |env |
418- locale = env.get(" preferences" ).as(Preferences ).locale
419-
420- user = env.get? " user"
421- sid = env.get? " sid"
422- referer = get_referer(env)
423-
424- if ! user
425- next env.redirect referer
426- end
427-
428- user = user.as(User )
429- sid = sid.as(String )
430- csrf_token = generate_response(sid, {" :change_password" }, HMAC_KEY )
431-
432- templated " change_password"
433- end
434-
435- post " /change_password" do |env |
436- locale = env.get(" preferences" ).as(Preferences ).locale
437-
438- user = env.get? " user"
439- sid = env.get? " sid"
440- referer = get_referer(env)
441-
442- if ! user
443- next env.redirect referer
444- end
445-
446- user = user.as(User )
447- sid = sid.as(String )
448- token = env.params.body[" csrf_token" ]?
449-
450- # We don't store passwords for Google accounts
451- if ! user.password
452- next error_template(400 , " Cannot change password for Google accounts" )
453- end
454-
455- begin
456- validate_request(token, sid, env.request, HMAC_KEY , locale)
457- rescue ex
458- next error_template(400 , ex)
459- end
460-
461- password = env.params.body[" password" ]?
462- if ! password
463- next error_template(401 , " Password is a required field" )
464- end
465-
466- new_passwords = env.params.body.select { |k , v | k.match(/^new_password\[\d +\] $/ ) }.map { |k , v | v }
467-
468- if new_passwords.size <= 1 || new_passwords.uniq.size != 1
469- next error_template(400 , " New passwords must match" )
470- end
471-
472- new_password = new_passwords.uniq[0 ]
473- if new_password.empty?
474- next error_template(401 , " Password cannot be empty" )
475- end
476-
477- if new_password.bytesize > 55
478- next error_template(400 , " Password cannot be longer than 55 characters" )
479- end
480-
481- if ! Crypto ::Bcrypt ::Password .new(user.password.not_nil!).verify(password.byte_slice(0 , 55 ))
482- next error_template(401 , " Incorrect password" )
483- end
484-
485- new_password = Crypto ::Bcrypt ::Password .create(new_password, cost: 10 )
486- Invidious ::Database ::Users .update_password(user, new_password.to_s)
487-
488- env.redirect referer
489- end
490-
491- get " /delete_account" do |env |
492- locale = env.get(" preferences" ).as(Preferences ).locale
493-
494- user = env.get? " user"
495- sid = env.get? " sid"
496- referer = get_referer(env)
497-
498- if ! user
499- next env.redirect referer
500- end
501-
502- user = user.as(User )
503- sid = sid.as(String )
504- csrf_token = generate_response(sid, {" :delete_account" }, HMAC_KEY )
505-
506- templated " delete_account"
507- end
508-
509- post " /delete_account" do |env |
510- locale = env.get(" preferences" ).as(Preferences ).locale
511-
512- user = env.get? " user"
513- sid = env.get? " sid"
514- referer = get_referer(env)
515-
516- if ! user
517- next env.redirect referer
518- end
519-
520- user = user.as(User )
521- sid = sid.as(String )
522- token = env.params.body[" csrf_token" ]?
523-
524- begin
525- validate_request(token, sid, env.request, HMAC_KEY , locale)
526- rescue ex
527- next error_template(400 , ex)
528- end
529-
530- view_name = " subscriptions_#{ sha256(user.email) } "
531- Invidious ::Database ::Users .delete(user)
532- Invidious ::Database ::SessionIDs .delete(email: user.email)
533- PG_DB .exec(" DROP MATERIALIZED VIEW #{ view_name } " )
534-
535- env.request.cookies.each do |cookie |
536- cookie.expires = Time .utc(1990 , 1 , 1 )
537- env.response.cookies << cookie
538- end
539-
540- env.redirect referer
541- end
542-
543- get " /clear_watch_history" do |env |
544- locale = env.get(" preferences" ).as(Preferences ).locale
545-
546- user = env.get? " user"
547- sid = env.get? " sid"
548- referer = get_referer(env)
549-
550- if ! user
551- next env.redirect referer
552- end
553-
554- user = user.as(User )
555- sid = sid.as(String )
556- csrf_token = generate_response(sid, {" :clear_watch_history" }, HMAC_KEY )
557-
558- templated " clear_watch_history"
559- end
560-
561- post " /clear_watch_history" do |env |
562- locale = env.get(" preferences" ).as(Preferences ).locale
563-
564- user = env.get? " user"
565- sid = env.get? " sid"
566- referer = get_referer(env)
567-
568- if ! user
569- next env.redirect referer
570- end
571-
572- user = user.as(User )
573- sid = sid.as(String )
574- token = env.params.body[" csrf_token" ]?
575-
576- begin
577- validate_request(token, sid, env.request, HMAC_KEY , locale)
578- rescue ex
579- next error_template(400 , ex)
580- end
581-
582- Invidious ::Database ::Users .clear_watch_history(user)
583- env.redirect referer
584- end
585-
586- get " /authorize_token" do |env |
587- locale = env.get(" preferences" ).as(Preferences ).locale
588-
589- user = env.get? " user"
590- sid = env.get? " sid"
591- referer = get_referer(env)
592-
593- if ! user
594- next env.redirect referer
595- end
596-
597- user = user.as(User )
598- sid = sid.as(String )
599- csrf_token = generate_response(sid, {" :authorize_token" }, HMAC_KEY )
600-
601- scopes = env.params.query[" scopes" ]?.try & .split(" ," )
602- scopes ||= [] of String
603-
604- callback_url = env.params.query[" callback_url" ]?
605- if callback_url
606- callback_url = URI .parse(callback_url)
607- end
608-
609- expire = env.params.query[" expire" ]?.try & .to_i?
610-
611- templated " authorize_token"
612- end
613-
614- post " /authorize_token" do |env |
615- locale = env.get(" preferences" ).as(Preferences ).locale
616-
617- user = env.get? " user"
618- sid = env.get? " sid"
619- referer = get_referer(env)
620-
621- if ! user
622- next env.redirect referer
623- end
624-
625- user = env.get(" user" ).as(User )
626- sid = sid.as(String )
627- token = env.params.body[" csrf_token" ]?
628-
629- begin
630- validate_request(token, sid, env.request, HMAC_KEY , locale)
631- rescue ex
632- next error_template(400 , ex)
633- end
634-
635- scopes = env.params.body.select { |k , v | k.match(/^scopes\[\d +\] $/ ) }.map { |k , v | v }
636- callback_url = env.params.body[" callbackUrl" ]?
637- expire = env.params.body[" expire" ]?.try & .to_i?
638-
639- access_token = generate_token(user.email, scopes, expire, HMAC_KEY )
640-
641- if callback_url
642- access_token = URI .encode_www_form(access_token)
643- url = URI .parse(callback_url)
644-
645- if url.query
646- query = HTTP ::Params .parse(url.query.not_nil!)
647- else
648- query = HTTP ::Params .new
649- end
650-
651- query[" token" ] = access_token
652- url.query = query.to_s
653-
654- env.redirect url.to_s
655- else
656- csrf_token = " "
657- env.set " access_token" , access_token
658- templated " authorize_token"
659- end
660- end
661-
662- get " /token_manager" do |env |
663- locale = env.get(" preferences" ).as(Preferences ).locale
664-
665- user = env.get? " user"
666- sid = env.get? " sid"
667- referer = get_referer(env, " /subscription_manager" )
668-
669- if ! user
670- next env.redirect referer
671- end
672-
673- user = user.as(User )
674- tokens = Invidious ::Database ::SessionIDs .select_all(user.email)
675-
676- templated " token_manager"
677- end
678-
679- post " /token_ajax" do |env |
680- locale = env.get(" preferences" ).as(Preferences ).locale
681-
682- user = env.get? " user"
683- sid = env.get? " sid"
684- referer = get_referer(env)
685-
686- redirect = env.params.query[" redirect" ]?
687- redirect ||= " true"
688- redirect = redirect == " true"
689-
690- if ! user
691- if redirect
692- next env.redirect referer
693- else
694- next error_json(403 , " No such user" )
695- end
696- end
697-
698- user = user.as(User )
699- sid = sid.as(String )
700- token = env.params.body[" csrf_token" ]?
701-
702- begin
703- validate_request(token, sid, env.request, HMAC_KEY , locale)
704- rescue ex
705- if redirect
706- next error_template(400 , ex)
707- else
708- next error_json(400 , ex)
709- end
710- end
711-
712- if env.params.query[" action_revoke_token" ]?
713- action = " action_revoke_token"
714- else
715- next env.redirect referer
716- end
717-
718- session = env.params.query[" session" ]?
719- session ||= " "
720-
721- case action
722- when .starts_with? " action_revoke_token"
723- Invidious ::Database ::SessionIDs .delete(sid: session, email: user.email)
724- else
725- next error_json(400 , " Unsupported action #{ action } " )
726- end
727-
728- if redirect
729- env.redirect referer
730- else
731- env.response.content_type = " application/json"
732- " {}"
733- end
734- end
735-
736409# Channels
737410
738411{" /channel/:ucid/live" , " /user/:user/live" , " /c/:user/live" }.each do |route |
@@ -876,7 +549,7 @@ add_handler AuthHandler.new
876549add_handler DenyFrame .new
877550add_context_storage_type(Array (String ))
878551add_context_storage_type(Preferences )
879- add_context_storage_type(User )
552+ add_context_storage_type(Invidious :: User )
880553
881554Kemal .config.logger = LOGGER
882555Kemal .config.host_binding = Kemal .config.host_binding != " 0.0.0.0" ? Kemal .config.host_binding : CONFIG .host_binding
0 commit comments