Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/ci-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ jobs:
bundler-cache: true
- name: Prepare for testing
run: |
echo "${{ secrets.MASTER_KEY }}" > config/master.key
cp config/database.sample.yml config/database.yml
cp config/storage.sample.yml config/storage.yml
bundle exec rails db:create
Expand Down
2 changes: 1 addition & 1 deletion app/jobs/application_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ class ApplicationJob < ActiveJob::Base
# Most jobs are safe to ignore if the underlying records are no longer available
discard_on ActiveJob::DeserializationError

def initialize
def initialize(*args, **opts)
@job_id = SecureRandom.uuid
super
end
Expand Down
29 changes: 29 additions & 0 deletions app/jobs/mail_uncaptured_donations_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
class MailUncapturedDonationsJob < ApplicationJob
queue_as :default

def perform(*_args)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking: I don't think we need to parametrize it all, do we? We don't use the param anyway, so let's avoid creating mental overhead for those less familiar with the syntax.

intents = Stripe::PaymentIntent.list
mailed = 0
errors = 0
intents.auto_paging_each do |pi|
break unless Time.at(pi.created) >= 24.hours.ago
next unless pi.status == 'requires_payment_method'
next unless pi.metadata['user_id'].present?
next if pi.metadata['emailed'].present?

user = User.find(pi.metadata['user_id'])
symbol = { 'GBP' => '£', 'USD' => '$', 'EUR' => '€' }[pi.currency.upcase]
amount = pi.amount / 100
DonationMailer.with(currency: symbol, amount: amount, email: user.email, name: user.username, intent: pi)
.donation_uncaptured.deliver_now
Stripe::PaymentIntent.update(pi.id, { metadata: { emailed: true } })
logger.debug "Mailed ##{user.id} for PaymentIntent #{pi.id}"
mailed += 1
rescue => e
Stripe::PaymentIntent.update(pi.id, { metadata: { email_error: e.message.to_s } })
logger.error "Error sending email for user #{user.id}, PaymentIntent #{pi.id}: #{e.message}"
errors += 1
end
logger.info "Mailed #{mailed} donations, #{errors} errors"
end
end
55 changes: 55 additions & 0 deletions app/jobs/recalc_abilities_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
class RecalcAbilitiesJob < ApplicationJob
queue_as :default

##
# Perform ability recalculations.
# @param options [Hash] additional options for the job. Currently supports +verbose+ and +quiet+.
def perform(**options)
resolved = []
destroy = []
all = AbilityQueue.pending.to_a

all.each do |q|
cu = q.community_user
u = cu&.user

if cu.nil? || u.nil?
destroy << q.id
next
end

RequestContext.community = cu.community

if options[:verbose] && !options[:quiet]
logger.debug "Scope: Community : #{cu.community.name} (#{cu.community.host})"
logger.debug " User : #{u.username} (#{cu.user_id})"
logger.debug " CommunityUser : #{cu.id}"
elsif !options[:verbose] && !options[:quiet]
logger.debug "Scope: CommunityUser : #{cu.id}"
end

cu.recalc_abilities!

# Grant mod ability if mod status is given
if cu.at_least_moderator? && !cu.ability?('mod')
cu.grant_ability!('mod')
end

resolved << q.id
rescue => e
logger.error " Failed: #{e.class.name}: #{e.message}"
logger.error e.backtrace

if Rails.env.test?
raise e
end
end

AbilityQueue.where(id: resolved).update(completed: true)
AbilityQueue.where(id: destroy).delete_all

unless options[:quiet]
logger.info "Completed, #{resolved.size}/#{all.size} tasks successful, #{destroy.size} tasks invalid"
end
end
end
2 changes: 1 addition & 1 deletion config/credentials.yml.enc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
SA7h7Xm7xF3AEvje/xZiPMzem0wh2CysuvvB+iM6R0Epkg+z+vZG2oxI/9tVzDGELWtwoNDPeqNa0bUbGjo6gt7xyEpmQbivEVKnwcbVK+1bxPHKke+hveVEUhmY/axFIIpty+VTnZVnrJkZ35/rW9egcRr5O2HikuAuBz8KrYLvB2w3h8EdmcIbbfjMvKWlUVvc8D9t3v+k56B1CbTghTmGeG0NLijWAA+U+pDmErPOR9JUAVY/nbF2/T8aQ5Szameuoj88Pk5P6alFDHwlWUSHhuEY5Z7A5LKM1NtzlTGc+CAcTVzKvx6DCg8WUJugy3uS7Bpp6uNj9TvJoZzrb0i5G1nDmIl7tK2GCNclp3JFEklrUJIrF4asRuDQUzdvuPeTEXNyi2cc5d6hSBG+MwEvG90P6n0td5+gv+rr1FCKuzP5ftyxqPsnvZuBKRxNSw0+VTTXhTO73jcwttHYrD9Jwc9tVbCVqegwsEO0dB0sNL6M89rudDMbpPnz7rJXr6lXD4Az3qJ/0N3ubYDwiuGOk7UHDntm4Id4BFDm5qeLeOUg1n2PDhsQUWh2Lfnk7ADvjQMinfXhdAQkYVim9sDtNO/Grn9xSXfCn3vs1xOdTtKLb23+EIxO2STtkHTsJG5XvxC2jmzL5/zQx/vO/zepHom7POdso4Ygoqw9oEttm/KPG85lcX0edXv/l1i5JBMMbzaQgd1PL4uWwrv+3LoSq+vQORijR50OiLdlMZ5IFn+QagJEdeVtUiCbYA3AhUK/FcH3L5QtSGNObEUrUJ4fVuWP6X8E34vd+DoY++D6PtG89SFIGBRmQ23cT111uIw3p2A9HP4N9B/uNKwxAnr4S1he6EkoA5CtDE0NZufy25s0IVf//FDWXS8FDg3ZhtOUeMWB0dew9VeCCWwr8RrLu4jP46IvVqfFeiVWf7gJcenEJ0QuqPlBeukSpgNxckDjwijRz5obzeS9ZAWYgCZg2kg/6CmuIM2VjkWMJ13uKYkFgpheoNsk1jZwH4+0fdm+Zc+fE4KQFcSkkazea/qEanN2/tDo6pRowSlRpi/nWJqHxcu87QMm7cBq5/E9DNjwyKOPmgr7c2NzDrlPYMRgzdcauPz6Y4qfcg9C6lKwJIo18VQhrqwh7wW+nNTov3Shw/yclkVrxnHTQbyH3mOstJsVPpYeYewxOQj/gikvvkx/lUeUnyo2/Ebff2nJCbnLmJ8/7Vwz9c/yvg==--d1HPd+AnhFU1woqD--z2ikkRr6d5WTzC7X5xOVPA==
ukMy8KvWRehfYquyl3GRlaSkFk/8OAjIw3HK2LIH4u1HhtiY2XrkXbwg3rKeCofCW1K5lxNf7r+w+v0IMfVnOkmOPI0eB/TNotrq0ieomzMnhYOXzBBQb/31vFFMFCGOZIRbk9vyduQGg/wifWMjoEk9ooL++YP2q+fXm/80d2gDF/G4hMNgdAq0SFPjn3cVM2Qty1ru1BuOJwgqo4yKDBjvuL7ZOxudDuPnKujY2IpgykCkKCk7TE80v9B4ZKdIi27P1ciWmP5Kc50jk7SWlhHVbo3FdJy1a/n5RadGq/vdlwOXFdyNUvlRF7xRvjlgiqoyqDHcyOuOyIP86v2qgeDl5Y7yYwIhe8FwqPy/oW/jMDP8OvDZuWtNwpxIFJYT7sKdvIvEvjrPR+0pyTVsVMZomTiUIcFC/IA9KV+DVjtj+Tfy2UZH4W8AU6i8hObiSs4CbT081L2AHc0ZcLKMI/bh8+vBay4J2UB6vcBbpNbAaNPyj7bXsrM0+YxpPJidgrEMyoVt+fIiA5H/kXhp8WV3Jkr2eEriq5z9+m6IZFSFs58i06hN0ZH5WHUdhJcVIgMBiLOex4SVd9zL6NW2y+ZK9Fs27z8u22zn+51oQHcpz2wbmVV3sGBYaFLFinqm3/HoW60eAcvM4SfXErz0fwIzq7yN7XIY9q5/6E0hhAdHZQqVlEJWOhUAIH9ik+Ga90gWLfkkoym/G1PIUYnmeJtLUKYyj94b+YdxQNkgzGtJA7FCGVmNUuy8wCw0OIG1hg3z9TSg5mbN7ZNhBRVDvKQENJqg9tFXM0MgXn+lQ0v+io4ds6Ist2BGr4gJIz5R7bRFOIG6G60/+ZEfPBjNcj5rrGYDBATmqKo9myaSLQ68WyJB37Fs3CchM4lAdoVbXnEyJwP8HGRaips+ZhjBVvSs/8w7yQteBswFrc00+gts5TpqCz3AjNNMsHTP5cr5IhqoNWdpxvFgHHLBAPtn0HWJ5C3OP3X/4GhxG3G9Z99pxbH1ZjWn1vnKadKUfY4vzPYCZsMaokTr2/XuL8wROLohCD53SVATsGsbiL947u+X6WYEZVuOH2IY5xMhTO9JW8DYb0Rm31Te8oOpzoIrz9Ck70YDQcADiNg4SEeLTQlpve40C5+YI5Xr+60GbOHRHSGv31ENnubVTCTv3q6otE0iqCOAQ62RdqhzT23aaz0NuH5DtLIlWn/3ev9Js6mm1rnF7AzVKey01IsS--p3woHV6iIC4KuPxP--fRXQKncEML1whOWmVm2Z8w==
33 changes: 0 additions & 33 deletions scripts/change_to_wilson_scores.rb

This file was deleted.

2 changes: 1 addition & 1 deletion scripts/cleanup_votes.rb
Original file line number Diff line number Diff line change
@@ -1 +1 @@
CleanupVotesJob.perform_later
CleanupVotesJob.perform_now
4 changes: 0 additions & 4 deletions scripts/create_backup_2fa_codes.rb

This file was deleted.

15 changes: 0 additions & 15 deletions scripts/create_general_thread_for_old_comments.rb

This file was deleted.

19 changes: 1 addition & 18 deletions scripts/mail_uncaptured_donations.rb
Original file line number Diff line number Diff line change
@@ -1,18 +1 @@
intents = Stripe::PaymentIntent.list
intents.auto_paging_each do |pi|
begin
break unless Time.at(pi.created) >= 24.hours.ago
next unless pi.status == 'requires_payment_method'
next unless pi.metadata['user_id'].present?
next if pi.metadata['emailed'].present?
user = User.find(pi.metadata['user_id'])
symbol = { 'GBP' => '£', 'USD' => '$', 'EUR' => '€' }[pi.currency.upcase]
amount = pi.amount / 100
DonationMailer.with(currency: symbol, amount: amount, email: user.email, name: user.username, intent: pi)
.donation_uncaptured.deliver_now
Stripe::PaymentIntent.update(pi.id, { metadata: { emailed: true } })
puts "Mailed ##{user.id} for PaymentIntent #{pi.id}"
rescue => ex
Stripe::PaymentIntent.update(pi.id, { metadata: { email_error: "#{ex.message}" } })
end
end
MailUncapturedDonations.perform_now
51 changes: 4 additions & 47 deletions scripts/recalc_abilities.rb
Original file line number Diff line number Diff line change
@@ -1,58 +1,15 @@
options = OpenStruct.new
options = {}

OptionParser.new do |opts|
opts.banner = "Usage: rails r scripts/recalc_abilities.rb [options]"

opts.on('-v', '--verbose', 'Run with additional logging') do
options.verbose = true
options[:verbose] = true
end

opts.on('-q', '--quiet', 'Run with minimal logging') do
options.quiet = true
options[:quiet] = true
end
end.parse!

resolved = []
destroy = []
all = AbilityQueue.pending.to_a

all.each do |q|
begin
cu = q.community_user
u = cu&.user

if cu.nil? || u.nil?
destroy << q.id
next
end

RequestContext.community = cu.community

if options.verbose && !options.quiet
puts "Scope: Community : #{cu.community.name} (#{cu.community.host})"
puts " User : #{u.username} (#{cu.user_id})"
puts " CommunityUser : #{cu.id}"
elsif !options.verbose && !options.quiet
puts "Scope: CommunityUser : #{cu.id}"
end

cu.recalc_abilities

# Grant mod ability if mod status is given
if cu.at_least_moderator? && !cu.ability?('mod')
cu.grant_ability!('mod')
end

resolved << q.id
rescue => e
$stderr.puts " Failed: #{e.class.name}: #{e.message}"
$stderr.puts e.backtrace
end
end

AbilityQueue.where(id: resolved).update(completed: true)
AbilityQueue.where(id: destroy).delete_all

unless options.quiet
puts "Completed, #{resolved.size}/#{all.size} tasks successful, #{destroy.size} tasks invalid"
end
RecalcAbilitiesJob.perform_now(options)
26 changes: 0 additions & 26 deletions scripts/recalc_abilities_upon_first_migration.rb

This file was deleted.

2 changes: 1 addition & 1 deletion scripts/run_complaints_closure.rb
Original file line number Diff line number Diff line change
@@ -1 +1 @@
AutoCloseComplaintsJob.perform_later
AutoCloseComplaintsJob.perform_now
2 changes: 1 addition & 1 deletion scripts/run_new_thread_followers_cleanup.rb
Original file line number Diff line number Diff line change
@@ -1 +1 @@
CleanUpNewThreadFollowersJob.perform_later
CleanUpNewThreadFollowersJob.perform_now
4 changes: 2 additions & 2 deletions scripts/run_spam_cleanup.rb
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
CleanUpSpammyUsersJob.perform_later
PotentialSpamProfilesJob.perform_later
CleanUpSpammyUsersJob.perform_now
PotentialSpamProfilesJob.perform_now
2 changes: 1 addition & 1 deletion scripts/run_summary_mailer.rb
Original file line number Diff line number Diff line change
@@ -1 +1 @@
SendSummaryEmailsJob.perform_later
SendSummaryEmailsJob.perform_now
2 changes: 1 addition & 1 deletion scripts/run_thread_followers_cleanup.rb
Original file line number Diff line number Diff line change
@@ -1 +1 @@
CleanUpThreadFollowersJob.perform_later
CleanUpThreadFollowersJob.perform_now
8 changes: 8 additions & 0 deletions test/controllers/donations_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@
class DonationsControllerTest < ActionController::TestCase
include Devise::Test::ControllerHelpers

setup do
WebMock.allow_net_connect!
end

teardown do
WebMock.disable_net_connect!
end

test 'should get index' do
get :index
assert_response(:success)
Expand Down
20 changes: 20 additions & 0 deletions test/jobs/mail_uncaptured_donations_job_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
require 'test_helper'

class MailUncapturedDonationsJobTest < ActiveJob::TestCase
setup do
WebMock.allow_net_connect!
end

teardown do
WebMock.disable_net_connect!
end

test 'should run job successfully' do
skip unless Stripe.api_key
WebMock.allow_net_connect!
perform_enqueued_jobs do
MailUncapturedDonationsJob.perform_later
end
assert_performed_jobs 1
end
end
10 changes: 10 additions & 0 deletions test/jobs/recalc_abilities_job_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
require 'test_helper'

class RecalcAbilitiesJobTest < ActiveJob::TestCase
test 'should run job successfully' do
perform_enqueued_jobs do
RecalcAbilitiesJob.perform_later(verbose: false, quiet: true)
end
assert_performed_jobs 1
end
end