summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOmar Roth <omarroth@hotmail.com>2018-11-08 00:12:14 -0600
committerOmar Roth <omarroth@hotmail.com>2018-11-08 00:12:14 -0600
commitb9c29bf537e3b5a64c8df7a29377e06596a7aee4 (patch)
tree74cdf8782896cac4ab4672576128473e6ae4ec86
parentf98812382091c0ab12f4981c803c532f59f0c911 (diff)
downloadinvidious-b9c29bf537e3b5a64c8df7a29377e06596a7aee4.tar.gz
invidious-b9c29bf537e3b5a64c8df7a29377e06596a7aee4.tar.bz2
invidious-b9c29bf537e3b5a64c8df7a29377e06596a7aee4.zip
Add option for user to delete their account
-rw-r--r--src/invidious.cr72
-rw-r--r--src/invidious/helpers/helpers.cr48
-rw-r--r--src/invidious/views/clear_watch_history.ecr17
-rw-r--r--src/invidious/views/delete_account.ecr17
-rw-r--r--src/invidious/views/preferences.ecr8
5 files changed, 159 insertions, 3 deletions
diff --git a/src/invidious.cr b/src/invidious.cr
index 3c251d96..7cf60531 100644
--- a/src/invidious.cr
+++ b/src/invidious.cr
@@ -896,6 +896,7 @@ post "/login" do |env|
end
end
+# TODO: Update this with using the same method for /clear_watch_history to prevent CSRF
get "/signout" do |env|
referer = get_referer(env)
@@ -910,7 +911,7 @@ get "/signout" do |env|
end
env.request.cookies.add_response_headers(env.response.headers)
- env.redirect URI.unescape(referer)
+ env.redirect referer
end
get "/preferences" do |env|
@@ -1402,14 +1403,83 @@ get "/subscription_ajax" do |env|
env.redirect referer
end
+get "/delete_account" do |env|
+ user = env.get? "user"
+ referer = get_referer(env)
+
+ if user
+ user = user.as(User)
+
+ challenge, token = create_response(user.email, "delete_account", HMAC_KEY)
+
+ templated "delete_account"
+ else
+ env.redirect referer
+ end
+end
+
+post "/delete_account" do |env|
+ user = env.get? "user"
+ referer = get_referer(env)
+
+ if user
+ user = user.as(User)
+
+ challenge = env.params.body["challenge"]?
+ token = env.params.body["token"]?
+
+ begin
+ validate_response(challenge, token, "delete_account", HMAC_KEY)
+ rescue ex
+ error_message = ex.message
+ next templated "error"
+ end
+
+ view_name = "subscriptions_#{sha256(user.email)[0..7]}"
+ PG_DB.exec("DROP MATERIALIZED VIEW #{view_name}")
+ PG_DB.exec("DELETE FROM users * WHERE email = $1", user.email)
+
+ env.request.cookies.each do |cookie|
+ cookie.expires = Time.new(1990, 1, 1)
+ end
+ env.request.cookies.add_response_headers(env.response.headers)
+ end
+
+ env.redirect referer
+end
+
get "/clear_watch_history" do |env|
user = env.get? "user"
+ referer = get_referer(env)
+ if user
+ user = user.as(User)
+
+ challenge, token = create_response(user.email, "clear_watch_history", HMAC_KEY)
+
+ templated "clear_watch_history"
+ else
+ env.redirect referer
+ end
+end
+
+post "/clear_watch_history" do |env|
+ user = env.get? "user"
referer = get_referer(env)
if user
user = user.as(User)
+ challenge = env.params.body["challenge"]?
+ token = env.params.body["token"]?
+
+ begin
+ validate_response(challenge, token, "clear_watch_history", HMAC_KEY)
+ rescue ex
+ error_message = ex.message
+ next templated "error"
+ end
+
PG_DB.exec("UPDATE users SET watched = '{}' WHERE email = $1", user.email)
end
diff --git a/src/invidious/helpers/helpers.cr b/src/invidious/helpers/helpers.cr
index 92a2e1b1..65493790 100644
--- a/src/invidious/helpers/helpers.cr
+++ b/src/invidious/helpers/helpers.cr
@@ -389,3 +389,51 @@ def extract_items(nodeset, ucid = nil)
return items
end
+
+def create_response(user_id, operation, key)
+ nonce = Random::Secure.hex(4)
+ expire = Time.now + 6.hours
+
+ challenge = "#{expire.to_unix}-#{nonce}-#{user_id}-#{operation}"
+ token = OpenSSL::HMAC.digest(:sha256, key, challenge)
+
+ challenge = Base64.urlsafe_encode(challenge)
+ token = Base64.urlsafe_encode(token)
+
+ return challenge, token
+end
+
+def validate_response(challenge, token, action, key)
+ if !challenge
+ raise "Hidden field \"challenge\" is a required field"
+ end
+
+ if !token
+ raise "Hidden field \"token\" is a required field"
+ end
+
+ challenge = Base64.decode_string(challenge)
+ if challenge.split("-").size == 4
+ expire, nonce, user_id, operation = challenge.split("-")
+
+ expire = expire.to_i?
+ expire ||= 0
+ else
+ raise "Invalid challenge"
+ end
+
+ challenge = OpenSSL::HMAC.digest(:sha256, HMAC_KEY, challenge)
+ challenge = Base64.urlsafe_encode(challenge)
+
+ if challenge != token
+ raise "Invalid token"
+ end
+
+ if operation != action
+ raise "Invalid token"
+ end
+
+ if expire < Time.now.to_unix
+ raise "Token is expired, please try again"
+ end
+end
diff --git a/src/invidious/views/clear_watch_history.ecr b/src/invidious/views/clear_watch_history.ecr
new file mode 100644
index 00000000..9a726a68
--- /dev/null
+++ b/src/invidious/views/clear_watch_history.ecr
@@ -0,0 +1,17 @@
+<div class="h-box">
+ <form class="pure-form pure-form-aligned" action="/clear_watch_history?referer=<%= URI.escape(referer) %>" method="post">
+ <legend>Clear watch history?</legend>
+
+ <div class="pure-g">
+ <div class="pure-u-1-2">
+ <button type="submit" name="submit" value="clear_watch_history" class="pure-button pure-button-primary">Yes</button>
+ </div>
+ <div class="pure-u-1-2">
+ <a class="pure-button" href="<%= referer %>">No</a>
+ </div>
+ </div>
+
+ <input type="hidden" name="token" value="<%= token %>">
+ <input type="hidden" name="challenge" value="<%= challenge %>">
+ </form>
+</div>
diff --git a/src/invidious/views/delete_account.ecr b/src/invidious/views/delete_account.ecr
new file mode 100644
index 00000000..8f2b61d6
--- /dev/null
+++ b/src/invidious/views/delete_account.ecr
@@ -0,0 +1,17 @@
+<div class="h-box">
+ <form class="pure-form pure-form-aligned" action="/delete_account?referer=<%= URI.escape(referer) %>" method="post">
+ <legend>Delete account?</legend>
+
+ <div class="pure-g">
+ <div class="pure-u-1-2">
+ <button type="submit" name="submit" value="delete_account" class="pure-button pure-button-primary">Yes</button>
+ </div>
+ <div class="pure-u-1-2">
+ <a class="pure-button" href="<%= referer %>">No</a>
+ </div>
+ </div>
+
+ <input type="hidden" name="token" value="<%= token %>">
+ <input type="hidden" name="challenge" value="<%= challenge %>">
+ </form>
+</div>
diff --git a/src/invidious/views/preferences.ecr b/src/invidious/views/preferences.ecr
index be15a54d..72b1d609 100644
--- a/src/invidious/views/preferences.ecr
+++ b/src/invidious/views/preferences.ecr
@@ -150,17 +150,21 @@ function update_value(element) {
<legend>Data preferences</legend>
<div class="pure-control-group">
- <a href="/clear_watch_history?referer=<%= referer %>">Clear watch history</a>
+ <a href="/clear_watch_history?referer=<%= URI.escape(referer) %>">Clear watch history</a>
</div>
<div class="pure-control-group">
- <a href="/data_control?referer=<%= referer %>">Import/Export data</a>
+ <a href="/data_control?referer=<%= URI.escape(referer) %>">Import/Export data</a>
</div>
<div class="pure-control-group">
<a href="/subscription_manager">Manage subscriptions</a>
</div>
+ <div class="pure-control-group">
+ <a href="/delete_account?referer=<%= URI.escape(referer) %>">Delete account</a>
+ </div>
+
<div class="pure-controls">
<button type="submit" class="pure-button pure-button-primary">Save preferences</button>
</div>