summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSamantaz Fox <coding@samantaz.fr>2022-02-04 03:44:10 +0100
committerSamantaz Fox <coding@samantaz.fr>2022-02-07 17:15:22 +0100
commitad4a06fca5d11b57705540818d3eb4e86bb6ac14 (patch)
tree5bd80b371639be18e9804bdd8fbfb42cd877c544 /src
parentc04f45d5e36499e6faefd163e92c58fa1abaa7ae (diff)
downloadinvidious-ad4a06fca5d11b57705540818d3eb4e86bb6ac14.tar.gz
invidious-ad4a06fca5d11b57705540818d3eb4e86bb6ac14.tar.bz2
invidious-ad4a06fca5d11b57705540818d3eb4e86bb6ac14.zip
Move user captcha code to its own module
Diffstat (limited to 'src')
-rw-r--r--src/invidious.cr15
-rw-r--r--src/invidious/routes/login.cr4
-rw-r--r--src/invidious/user/captcha.cr78
-rw-r--r--src/invidious/users.cr69
4 files changed, 87 insertions, 79 deletions
diff --git a/src/invidious.cr b/src/invidious.cr
index 1e78ef5d..06ce3ead 100644
--- a/src/invidious.cr
+++ b/src/invidious.cr
@@ -38,14 +38,13 @@ require "./invidious/jobs/**"
CONFIG = Config.load
HMAC_KEY = CONFIG.hmac_key || Random::Secure.hex(32)
-PG_DB = DB.open CONFIG.database_url
-ARCHIVE_URL = URI.parse("https://archive.org")
-LOGIN_URL = URI.parse("https://accounts.google.com")
-PUBSUB_URL = URI.parse("https://pubsubhubbub.appspot.com")
-REDDIT_URL = URI.parse("https://www.reddit.com")
-TEXTCAPTCHA_URL = URI.parse("https://textcaptcha.com")
-YT_URL = URI.parse("https://www.youtube.com")
-HOST_URL = make_host_url(Kemal.config)
+PG_DB = DB.open CONFIG.database_url
+ARCHIVE_URL = URI.parse("https://archive.org")
+LOGIN_URL = URI.parse("https://accounts.google.com")
+PUBSUB_URL = URI.parse("https://pubsubhubbub.appspot.com")
+REDDIT_URL = URI.parse("https://www.reddit.com")
+YT_URL = URI.parse("https://www.youtube.com")
+HOST_URL = make_host_url(Kemal.config)
CHARS_SAFE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
TEST_IDS = {"AgbeGFYluEA", "BaW_jenozKc", "a9LDPn-MO4I", "ddFvjfvPnqk", "iqKdEhx-dD4"}
diff --git a/src/invidious/routes/login.cr b/src/invidious/routes/login.cr
index f4859e6f..42ac0b1d 100644
--- a/src/invidious/routes/login.cr
+++ b/src/invidious/routes/login.cr
@@ -393,9 +393,9 @@ module Invidious::Routes::Login
prompt = ""
if captcha_type == "image"
- captcha = generate_captcha(HMAC_KEY)
+ captcha = Invidious::User::Captcha.generate_image(HMAC_KEY)
else
- captcha = generate_text_captcha(HMAC_KEY)
+ captcha = Invidious::User::Captcha.generate_text(HMAC_KEY)
end
return templated "login"
diff --git a/src/invidious/user/captcha.cr b/src/invidious/user/captcha.cr
new file mode 100644
index 00000000..8a0f67e5
--- /dev/null
+++ b/src/invidious/user/captcha.cr
@@ -0,0 +1,78 @@
+require "openssl/hmac"
+
+struct Invidious::User
+ module Captcha
+ extend self
+
+ private TEXTCAPTCHA_URL = URI.parse("https://textcaptcha.com")
+
+ def generate_image(key)
+ second = Random::Secure.rand(12)
+ second_angle = second * 30
+ second = second * 5
+
+ minute = Random::Secure.rand(12)
+ minute_angle = minute * 30
+ minute = minute * 5
+
+ hour = Random::Secure.rand(12)
+ hour_angle = hour * 30 + minute_angle.to_f / 12
+ if hour == 0
+ hour = 12
+ end
+
+ clock_svg = <<-END_SVG
+ <svg viewBox="0 0 100 100" width="200px" height="200px">
+ <circle cx="50" cy="50" r="45" fill="#eee" stroke="black" stroke-width="2"></circle>
+
+ <text x="69" y="20.091" text-anchor="middle" fill="black" font-family="Arial" font-size="10px"> 1</text>
+ <text x="82.909" y="34" text-anchor="middle" fill="black" font-family="Arial" font-size="10px"> 2</text>
+ <text x="88" y="53" text-anchor="middle" fill="black" font-family="Arial" font-size="10px"> 3</text>
+ <text x="82.909" y="72" text-anchor="middle" fill="black" font-family="Arial" font-size="10px"> 4</text>
+ <text x="69" y="85.909" text-anchor="middle" fill="black" font-family="Arial" font-size="10px"> 5</text>
+ <text x="50" y="91" text-anchor="middle" fill="black" font-family="Arial" font-size="10px"> 6</text>
+ <text x="31" y="85.909" text-anchor="middle" fill="black" font-family="Arial" font-size="10px"> 7</text>
+ <text x="17.091" y="72" text-anchor="middle" fill="black" font-family="Arial" font-size="10px"> 8</text>
+ <text x="12" y="53" text-anchor="middle" fill="black" font-family="Arial" font-size="10px"> 9</text>
+ <text x="17.091" y="34" text-anchor="middle" fill="black" font-family="Arial" font-size="10px">10</text>
+ <text x="31" y="20.091" text-anchor="middle" fill="black" font-family="Arial" font-size="10px">11</text>
+ <text x="50" y="15" text-anchor="middle" fill="black" font-family="Arial" font-size="10px">12</text>
+
+ <circle cx="50" cy="50" r="3" fill="black"></circle>
+ <line id="second" transform="rotate(#{second_angle}, 50, 50)" x1="50" y1="50" x2="50" y2="12" fill="black" stroke="black" stroke-width="1"></line>
+ <line id="minute" transform="rotate(#{minute_angle}, 50, 50)" x1="50" y1="50" x2="50" y2="16" fill="black" stroke="black" stroke-width="2"></line>
+ <line id="hour" transform="rotate(#{hour_angle}, 50, 50)" x1="50" y1="50" x2="50" y2="24" fill="black" stroke="black" stroke-width="2"></line>
+ </svg>
+ END_SVG
+
+ image = "data:image/png;base64,"
+ image += Process.run(%(rsvg-convert -w 400 -h 400 -b none -f png), shell: true,
+ input: IO::Memory.new(clock_svg), output: Process::Redirect::Pipe
+ ) do |proc|
+ Base64.strict_encode(proc.output.gets_to_end)
+ end
+
+ answer = "#{hour}:#{minute.to_s.rjust(2, '0')}:#{second.to_s.rjust(2, '0')}"
+ answer = OpenSSL::HMAC.hexdigest(:sha256, key, answer)
+
+ return {
+ question: image,
+ tokens: {generate_response(answer, {":login"}, key, use_nonce: true)},
+ }
+ end
+
+ def generate_text(key)
+ response = make_client(TEXTCAPTCHA_URL, &.get("/github.com/iv.org/invidious.json").body)
+ response = JSON.parse(response)
+
+ tokens = response["a"].as_a.map do |answer|
+ generate_response(answer.as_s, {":login"}, key, use_nonce: true)
+ end
+
+ return {
+ question: response["q"].as_s,
+ tokens: tokens,
+ }
+ end
+ end
+end
diff --git a/src/invidious/users.cr b/src/invidious/users.cr
index b4995e95..b763596b 100644
--- a/src/invidious/users.cr
+++ b/src/invidious/users.cr
@@ -91,75 +91,6 @@ def create_user(sid, email, password)
return user, sid
end
-def generate_captcha(key)
- second = Random::Secure.rand(12)
- second_angle = second * 30
- second = second * 5
-
- minute = Random::Secure.rand(12)
- minute_angle = minute * 30
- minute = minute * 5
-
- hour = Random::Secure.rand(12)
- hour_angle = hour * 30 + minute_angle.to_f / 12
- if hour == 0
- hour = 12
- end
-
- clock_svg = <<-END_SVG
- <svg viewBox="0 0 100 100" width="200px" height="200px">
- <circle cx="50" cy="50" r="45" fill="#eee" stroke="black" stroke-width="2"></circle>
-
- <text x="69" y="20.091" text-anchor="middle" fill="black" font-family="Arial" font-size="10px"> 1</text>
- <text x="82.909" y="34" text-anchor="middle" fill="black" font-family="Arial" font-size="10px"> 2</text>
- <text x="88" y="53" text-anchor="middle" fill="black" font-family="Arial" font-size="10px"> 3</text>
- <text x="82.909" y="72" text-anchor="middle" fill="black" font-family="Arial" font-size="10px"> 4</text>
- <text x="69" y="85.909" text-anchor="middle" fill="black" font-family="Arial" font-size="10px"> 5</text>
- <text x="50" y="91" text-anchor="middle" fill="black" font-family="Arial" font-size="10px"> 6</text>
- <text x="31" y="85.909" text-anchor="middle" fill="black" font-family="Arial" font-size="10px"> 7</text>
- <text x="17.091" y="72" text-anchor="middle" fill="black" font-family="Arial" font-size="10px"> 8</text>
- <text x="12" y="53" text-anchor="middle" fill="black" font-family="Arial" font-size="10px"> 9</text>
- <text x="17.091" y="34" text-anchor="middle" fill="black" font-family="Arial" font-size="10px">10</text>
- <text x="31" y="20.091" text-anchor="middle" fill="black" font-family="Arial" font-size="10px">11</text>
- <text x="50" y="15" text-anchor="middle" fill="black" font-family="Arial" font-size="10px">12</text>
-
- <circle cx="50" cy="50" r="3" fill="black"></circle>
- <line id="second" transform="rotate(#{second_angle}, 50, 50)" x1="50" y1="50" x2="50" y2="12" fill="black" stroke="black" stroke-width="1"></line>
- <line id="minute" transform="rotate(#{minute_angle}, 50, 50)" x1="50" y1="50" x2="50" y2="16" fill="black" stroke="black" stroke-width="2"></line>
- <line id="hour" transform="rotate(#{hour_angle}, 50, 50)" x1="50" y1="50" x2="50" y2="24" fill="black" stroke="black" stroke-width="2"></line>
- </svg>
- END_SVG
-
- image = "data:image/png;base64,"
- image += Process.run(%(rsvg-convert -w 400 -h 400 -b none -f png), shell: true,
- input: IO::Memory.new(clock_svg), output: Process::Redirect::Pipe
- ) do |proc|
- Base64.strict_encode(proc.output.gets_to_end)
- end
-
- answer = "#{hour}:#{minute.to_s.rjust(2, '0')}:#{second.to_s.rjust(2, '0')}"
- answer = OpenSSL::HMAC.hexdigest(:sha256, key, answer)
-
- return {
- question: image,
- tokens: {generate_response(answer, {":login"}, key, use_nonce: true)},
- }
-end
-
-def generate_text_captcha(key)
- response = make_client(TEXTCAPTCHA_URL, &.get("/github.com/iv.org/invidious.json").body)
- response = JSON.parse(response)
-
- tokens = response["a"].as_a.map do |answer|
- generate_response(answer.as_s, {":login"}, key, use_nonce: true)
- end
-
- return {
- question: response["q"].as_s,
- tokens: tokens,
- }
-end
-
def subscribe_ajax(channel_id, action, env_headers)
headers = HTTP::Headers.new
headers["Cookie"] = env_headers["Cookie"]