From d600c36036c5c3b53787067682128ae2d86311bf Mon Sep 17 00:00:00 2001 From: Arpit Jalan Date: Fri, 5 Aug 2022 07:50:48 +0530 Subject: [PATCH] FIX: do not redeem expired invites on new user signup (#17798) --- app/models/invite.rb | 4 +++- app/models/invite_redeemer.rb | 2 ++ spec/models/email_token_spec.rb | 35 +++++++++++++++++++++++++++++++++ spec/models/invite_spec.rb | 26 ++++++++++++++++++------ 4 files changed, 60 insertions(+), 7 deletions(-) diff --git a/app/models/invite.rb b/app/models/invite.rb index f3c124436c3..d4922ecc1e7 100644 --- a/app/models/invite.rb +++ b/app/models/invite.rb @@ -182,7 +182,9 @@ class Invite < ActiveRecord::Base def self.redeem_from_email(email) invite = Invite.find_by(email: Email.downcase(email)) - InviteRedeemer.new(invite: invite, email: invite.email).redeem if invite + if invite.present? && invite.redeemable? + InviteRedeemer.new(invite: invite, email: invite.email).redeem + end invite end diff --git a/app/models/invite_redeemer.rb b/app/models/invite_redeemer.rb index 1993ad01a8e..ed0a115f4b3 100644 --- a/app/models/invite_redeemer.rb +++ b/app/models/invite_redeemer.rb @@ -82,6 +82,8 @@ InviteRedeemer = Struct.new(:invite, :email, :username, :name, :password, :user_ private def can_redeem_invite? + return false unless invite.redeemable? + # Invite has already been redeemed if !invite.is_invite_link? && InvitedUser.exists?(invite_id: invite.id) return false diff --git a/spec/models/email_token_spec.rb b/spec/models/email_token_spec.rb index 04ebd0e9fcf..0c068bf645a 100644 --- a/spec/models/email_token_spec.rb +++ b/spec/models/email_token_spec.rb @@ -173,5 +173,40 @@ RSpec.describe EmailToken do expect(confirmed_invited_user).to be_approved end end + + context 'with expired invite record' do + before do + SiteSetting.must_approve_users = true + Jobs.run_immediately! + end + + fab!(:invite) { Fabricate(:invite, email: 'test@example.com', expires_at: 1.day.ago) } + fab!(:invited_user) { Fabricate(:user, active: false, email: invite.email) } + let!(:user_email_token) { Fabricate(:email_token, user: invited_user, scope: EmailToken.scopes[:signup]) } + let!(:confirmed_invited_user) { EmailToken.confirm(user_email_token.token, scope: EmailToken.scopes[:signup]) } + + it "returns the correct user" do + expect(confirmed_invited_user).to eq invited_user + end + + it 'marks the user as active' do + confirmed_invited_user.reload + expect(confirmed_invited_user).to be_active + end + + it 'marks the token as confirmed' do + user_email_token.reload + expect(user_email_token).to be_confirmed + end + + it 'does not redeem invite' do + invite.reload + expect(invite).not_to be_redeemed + end + + it 'marks the user as approved' do + expect(confirmed_invited_user).to be_approved + end + end end end diff --git a/spec/models/invite_spec.rb b/spec/models/invite_spec.rb index e21b5169090..be2cd81414c 100644 --- a/spec/models/invite_spec.rb +++ b/spec/models/invite_spec.rb @@ -239,13 +239,8 @@ RSpec.describe Invite do expect(invite.redeem).to be_blank end - it 'does not work with deleted invites' do - invite.destroy! - expect(invite.redeem).to be_blank - end - it 'does not work with invalidated invites' do - invite.update(invalidated_at: 1.day.ago) + invite.update!(invalidated_at: 1.day.ago) expect(invite.redeem).to be_blank end @@ -317,6 +312,25 @@ RSpec.describe Invite do Invite.redeem_from_email('test2@example.com') expect(invite.reload).not_to be_redeemed end + + it 'does not work with expired invites' do + invite.update!(expires_at: 1.day.ago) + Invite.redeem_from_email(user.email) + expect(invite).not_to be_redeemed + end + + it 'does not work with deleted invites' do + invite.trash! + Invite.redeem_from_email(user.email) + expect(invite).not_to be_redeemed + end + + it 'does not work with invalidated invites' do + invite.update!(invalidated_at: 1.day.ago) + Invite.redeem_from_email(user.email) + expect(invite).not_to be_redeemed + end + end describe 'scopes' do