diff --git a/app/settings.rb b/app/settings.rb index 12373380..29387b36 100644 --- a/app/settings.rb +++ b/app/settings.rb @@ -15,7 +15,10 @@ def require_ownership_for_settings end end -get '/settings/:username/?' do +get '/settings/:username/?' do |username| + # This is for the email_unsubscribe below + pass if Site.select(:id).where(username: username).first.nil? + require_login require_ownership_for_settings erb :'settings/site' @@ -281,4 +284,20 @@ post '/settings/create_child' do flash[:error] = site.errors.first.last.first redirect '/settings#sites' end +end + +get '/settings/unsubscribe_email/?' do + redirect "/settings/#email" if signed_in? + + if params[:email] && params[:token] && params[:email] != '' && Site.valid_email_unsubscribe_token?(params[:email], params[:token]) + Site.where(email: params[:email]).all.each do |site| + site.send_emails = false + site.save_changes validate: false + end + + @message = "You have been successfully unsubscribed from future emails to #{params[:email]}. Our apologies for the inconvenience." + else + @message = 'There was an error unsubscribing your email address. Please contact support.' + end + erb :'settings/account/unsubscribe' end \ No newline at end of file diff --git a/models/site.rb b/models/site.rb index 5eba1a74..8ed6dfeb 100644 --- a/models/site.rb +++ b/models/site.rb @@ -206,6 +206,14 @@ class Site < Sequel::Model end class << self + def valid_email_unsubscribe_token?(email, token) + email_unsubscribe_token(email) == token + end + + def email_unsubscribe_token(email) + Digest::SHA2.hexdigest email+$config['email_unsubscribe_token'] + end + def valid_login?(username_or_email, plaintext) site = get_with_identifier username_or_email diff --git a/tests/acceptance/settings/account_tests.rb b/tests/acceptance/settings/account_tests.rb index f9d419c7..90a05483 100644 --- a/tests/acceptance/settings/account_tests.rb +++ b/tests/acceptance/settings/account_tests.rb @@ -66,6 +66,49 @@ describe 'site/settings' do end end + describe 'unsubscribe email' do + include Capybara::DSL + + before do + @email = "#{SecureRandom.uuid.gsub('-', '')}@example.com" + @site = Fabricate :site, email: @email + EmailWorker.jobs.clear + Mail::TestMailer.deliveries.clear + + @params = { + email: @site.email, + token: Site.email_unsubscribe_token(@site.email) + } + @params_query = Rack::Utils.build_query(@params) + + @email_unsubscribe_url = "https://neocities.org/settings/unsubscribe_email?"+@params_query + page.set_rack_session id: nil + end + + it 'should redirect to settings page if logged in' do + page.set_rack_session id: @site.id + + end + + it 'should unsubscribe for valid token' do + @site.send_email subject: 'Hello', body: 'Okay' + EmailWorker.drain + email = Mail::TestMailer.deliveries.first + + email.body.to_s.must_match @email_unsubscribe_url + @site.send_emails.must_equal true + visit '/settings/unsubscribe_email?'+@params_query + + page.body.must_match /You have been successfully unsubscribed.+#{@site.email}/i + + @site.reload.send_emails.must_equal false + end + + it 'should fail to subscribe for bad token' do + + end + end + describe 'change password' do include Capybara::DSL diff --git a/tests/workers/email_worker_tests.rb b/tests/workers/email_worker_tests.rb index 3b168429..05345ba3 100644 --- a/tests/workers/email_worker_tests.rb +++ b/tests/workers/email_worker_tests.rb @@ -18,6 +18,9 @@ describe EmailWorker do mail.from.first.must_equal 'from@example.com' mail.to.first.must_equal 'to@example.com' mail.subject.must_equal 'Hello World' - mail.body.to_s.must_equal 'testing' + body = mail.body.to_s + puts body + body.must_match /testing/ + body.must_match /unsubscribe/ end end \ No newline at end of file diff --git a/views/settings/account/unsubscribe.erb b/views/settings/account/unsubscribe.erb new file mode 100644 index 00000000..03157256 --- /dev/null +++ b/views/settings/account/unsubscribe.erb @@ -0,0 +1,11 @@ +