diff --git a/app/models/invite.rb b/app/models/invite.rb index d95baebb8e3..9a5acc73b0b 100644 --- a/app/models/invite.rb +++ b/app/models/invite.rb @@ -41,47 +41,7 @@ class Invite < ActiveRecord::Base end def redeem - result = nil - Invite.transaction do - # Avoid a race condition - row_count = Invite.update_all('redeemed_at = CURRENT_TIMESTAMP', - ['id = ? AND redeemed_at IS NULL AND created_at >= ?', id, SiteSetting.invite_expiry_days.days.ago]) - - if row_count == 1 - - # Create the user if we are redeeming the invite and the user doesn't exist - result = User.where(email: email).first - result ||= User.create_for_email(email, trust_level: SiteSetting.default_invitee_trust_level) - result.send_welcome_message = false - - # If there are topic invites for private topics - topics.private_messages.each do |t| - t.topic_allowed_users.create(user_id: result.id) - end - - # Check for other invites by the same email. Don't redeem them, but approve their - # topics. - Invite.where('invites.email = ? and invites.id != ?', email, id).includes(:topics).where(topics: { archetype: Archetype::private_message }).each do |i| - i.topics.each do |t| - t.topic_allowed_users.create(user_id: result.id) - end - end - - if Invite.update_all(['user_id = ?', result.id], ['email = ?', email]) == 1 - result.send_welcome_message = true - end - - # Notify the invitee - invited_by.notifications.create(notification_type: Notification.types[:invitee_accepted], - data: { display_username: result.username }.to_json) - - else - # Otherwise return the existing user - result = User.where(email: email).first - end - end - - result + InviteRedeemer.new(self).redeem unless expired? || destroyed? end end diff --git a/app/models/invite_redeemer.rb b/app/models/invite_redeemer.rb new file mode 100644 index 00000000000..64533fa73e2 --- /dev/null +++ b/app/models/invite_redeemer.rb @@ -0,0 +1,74 @@ +InviteRedeemer = Struct.new(:invite) do + + def redeem + Invite.transaction do + process_invitation if invite_was_redeemed? + end + + invited_user + end + + private + + def invited_user + @invited_user ||= get_invited_user + end + + def process_invitation + add_to_private_topics_if_invited + add_user_to_invited_topics + send_welcome_message + notify_invitee + end + + def invite_was_redeemed? + # Return true if a row was updated + mark_invite_redeemed == 1 + end + + def mark_invite_redeemed + Invite.update_all('redeemed_at = CURRENT_TIMESTAMP', + ['id = ? AND redeemed_at IS NULL AND created_at >= ?', + invite.id, SiteSetting.invite_expiry_days.days.ago]) + end + + def get_invited_user + result = get_existing_user + result ||= create_new_user + result.send_welcome_message = false + result + end + + def get_existing_user + User.where(email: invite.email).first + end + + def create_new_user + User.create_for_email(invite.email, trust_level: SiteSetting.default_invitee_trust_level) + end + + def add_to_private_topics_if_invited + invite.topics.private_messages.each do |t| + t.topic_allowed_users.create(user_id: invited_user.id) + end + end + + def add_user_to_invited_topics + Invite.where('invites.email = ? and invites.id != ?', invite.email, invite.id).includes(:topics).where(topics: {archetype: Archetype::private_message}).each do |i| + i.topics.each do |t| + t.topic_allowed_users.create(user_id: invited_user.id) + end + end + end + + def send_welcome_message + if Invite.update_all(['user_id = ?', invited_user.id], ['email = ?', invite.email]) == 1 + invited_user.send_welcome_message = true + end + end + + def notify_invitee + invite.invited_by.notifications.create(notification_type: Notification.types[:invitee_accepted], + data: {display_username: invited_user.username}.to_json) + end +end \ No newline at end of file