From 8904487324fd7dc4fc9818fb975926e9defef42d Mon Sep 17 00:00:00 2001 From: ThibG Date: Fri, 26 Jul 2019 18:55:33 +0200 Subject: [PATCH] Fix invites not being disabled upon account suspension (#11412) * Disable invite links from disabled/suspended users * Add has_many invites relationship to users * Destroy unused invites when suspending an account --- app/controllers/invites_controller.rb | 2 +- app/models/invite.rb | 4 ++-- app/models/user.rb | 1 + app/services/suspend_account_service.rb | 1 + spec/models/invite_spec.rb | 16 +++++++++++----- 5 files changed, 16 insertions(+), 8 deletions(-) diff --git a/app/controllers/invites_controller.rb b/app/controllers/invites_controller.rb index fdb3a0962..de5280305 100644 --- a/app/controllers/invites_controller.rb +++ b/app/controllers/invites_controller.rb @@ -39,7 +39,7 @@ class InvitesController < ApplicationController private def invites - Invite.where(user: current_user).order(id: :desc) + current_user.invites.order(id: :desc) end def resource_params diff --git a/app/models/invite.rb b/app/models/invite.rb index fe2322462..02ab8e0b2 100644 --- a/app/models/invite.rb +++ b/app/models/invite.rb @@ -17,7 +17,7 @@ class Invite < ApplicationRecord include Expireable - belongs_to :user + belongs_to :user, inverse_of: :invites has_many :users, inverse_of: :invite scope :available, -> { where(expires_at: nil).or(where('expires_at >= ?', Time.now.utc)) } @@ -25,7 +25,7 @@ class Invite < ApplicationRecord before_validation :set_code def valid_for_use? - (max_uses.nil? || uses < max_uses) && !expired? + (max_uses.nil? || uses < max_uses) && !expired? && !(user.nil? || user.disabled?) end private diff --git a/app/models/user.rb b/app/models/user.rb index 50873dd01..a44c9c9c1 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -73,6 +73,7 @@ class User < ApplicationRecord has_many :applications, class_name: 'Doorkeeper::Application', as: :owner has_many :backups, inverse_of: :user + has_many :invites, inverse_of: :user has_one :invite_request, class_name: 'UserInviteRequest', inverse_of: :user, dependent: :destroy accepts_nested_attributes_for :invite_request, reject_if: ->(attributes) { attributes['text'].blank? } diff --git a/app/services/suspend_account_service.rb b/app/services/suspend_account_service.rb index a5ce3dbd9..5dd01da52 100644 --- a/app/services/suspend_account_service.rb +++ b/app/services/suspend_account_service.rb @@ -66,6 +66,7 @@ class SuspendAccountService < BaseService @account.user.destroy else @account.user.disable! + @account.user.invites.where(uses: 0).destroy_all end end diff --git a/spec/models/invite_spec.rb b/spec/models/invite_spec.rb index 0ba1dccb3..30abfb86b 100644 --- a/spec/models/invite_spec.rb +++ b/spec/models/invite_spec.rb @@ -3,27 +3,33 @@ require 'rails_helper' RSpec.describe Invite, type: :model do describe '#valid_for_use?' do it 'returns true when there are no limitations' do - invite = Invite.new(max_uses: nil, expires_at: nil) + invite = Fabricate(:invite, max_uses: nil, expires_at: nil) expect(invite.valid_for_use?).to be true end it 'returns true when not expired' do - invite = Invite.new(max_uses: nil, expires_at: 1.hour.from_now) + invite = Fabricate(:invite, max_uses: nil, expires_at: 1.hour.from_now) expect(invite.valid_for_use?).to be true end it 'returns false when expired' do - invite = Invite.new(max_uses: nil, expires_at: 1.hour.ago) + invite = Fabricate(:invite, max_uses: nil, expires_at: 1.hour.ago) expect(invite.valid_for_use?).to be false end it 'returns true when uses still available' do - invite = Invite.new(max_uses: 250, uses: 249, expires_at: nil) + invite = Fabricate(:invite, max_uses: 250, uses: 249, expires_at: nil) expect(invite.valid_for_use?).to be true end it 'returns false when maximum uses reached' do - invite = Invite.new(max_uses: 250, uses: 250, expires_at: nil) + invite = Fabricate(:invite, max_uses: 250, uses: 250, expires_at: nil) + expect(invite.valid_for_use?).to be false + end + + it 'returns false when invite creator has been disabled' do + invite = Fabricate(:invite, max_uses: nil, expires_at: nil) + SuspendAccountService.new.call(invite.user.account) expect(invite.valid_for_use?).to be false end end