2017-02-24 17:27:27 +00:00
|
|
|
require 'rails_helper'
|
2017-06-16 20:43:09 +00:00
|
|
|
require 'models/concerns/has_groups_examples'
|
|
|
|
require 'models/concerns/has_roles_examples'
|
2017-06-20 15:13:42 +00:00
|
|
|
require 'models/concerns/has_groups_permissions_examples'
|
2018-07-05 15:43:52 +00:00
|
|
|
require 'models/concerns/can_lookup_examples'
|
2017-02-24 17:27:27 +00:00
|
|
|
|
|
|
|
RSpec.describe User do
|
2018-07-23 08:28:21 +00:00
|
|
|
let(:subject) { create(:user, user_attrs || {}) }
|
2018-03-08 12:23:37 +00:00
|
|
|
let(:group_access_instance) { create(:agent_user) }
|
|
|
|
let(:new_group_access_instance) { build(:agent_user) }
|
2017-06-20 15:13:42 +00:00
|
|
|
let(:group_access_no_permission_instance) { build(:user) }
|
|
|
|
|
2017-06-16 20:43:09 +00:00
|
|
|
include_examples 'HasGroups'
|
|
|
|
include_examples 'HasRoles'
|
2017-06-20 15:13:42 +00:00
|
|
|
include_examples 'HasGroups and Permissions'
|
2018-07-05 13:24:26 +00:00
|
|
|
include_examples 'CanLookup'
|
2017-02-24 17:27:27 +00:00
|
|
|
|
|
|
|
let(:new_password) { 'N3W54V3PW!' }
|
|
|
|
|
|
|
|
context 'password' do
|
|
|
|
|
|
|
|
it 'resets login_failed on password change' do
|
2018-03-08 12:23:37 +00:00
|
|
|
|
|
|
|
failed_logins = (Setting.get('password_max_login_failed').to_i || 10) + 1
|
|
|
|
user = create(:user, login_failed: failed_logins)
|
|
|
|
|
2017-10-01 12:25:52 +00:00
|
|
|
expect do
|
2017-02-24 17:27:27 +00:00
|
|
|
user.password = new_password
|
|
|
|
user.save
|
2017-10-01 12:25:52 +00:00
|
|
|
end.to change { user.login_failed }.to(0)
|
2017-02-24 17:27:27 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-09-05 09:49:32 +00:00
|
|
|
context '#out_of_office_agent' do
|
|
|
|
|
|
|
|
it 'responds to out_of_office_agent' do
|
|
|
|
user = create(:user)
|
|
|
|
expect(user).to respond_to(:out_of_office_agent)
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'replacement' do
|
|
|
|
|
|
|
|
it 'finds assigned' do
|
|
|
|
user_replacement = create(:user)
|
|
|
|
|
|
|
|
user_ooo = create(:user,
|
|
|
|
out_of_office: true,
|
|
|
|
out_of_office_start_at: Time.zone.yesterday,
|
|
|
|
out_of_office_end_at: Time.zone.tomorrow,
|
|
|
|
out_of_office_replacement_id: user_replacement.id,)
|
|
|
|
|
|
|
|
expect(user_ooo.out_of_office_agent).to eq user_replacement
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'finds none for available users' do
|
|
|
|
user = create(:user)
|
|
|
|
expect(user.out_of_office_agent).to be nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-04-19 10:09:54 +00:00
|
|
|
context '#max_login_failed?' do
|
|
|
|
|
|
|
|
it 'responds to max_login_failed?' do
|
|
|
|
user = create(:user)
|
|
|
|
expect(user).to respond_to(:max_login_failed?)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'checks if a user has reached the maximum of failed logins' do
|
|
|
|
|
|
|
|
user = create(:user)
|
|
|
|
expect(user.max_login_failed?).to be false
|
|
|
|
|
|
|
|
user.login_failed = 999
|
|
|
|
user.save
|
|
|
|
expect(user.max_login_failed?).to be true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context '.identify' do
|
|
|
|
|
|
|
|
it 'returns users found by login' do
|
|
|
|
user = create(:user)
|
|
|
|
found_user = User.identify(user.login)
|
|
|
|
expect(found_user).to be_an(User)
|
|
|
|
expect(found_user.id).to eq user.id
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'returns users found by email' do
|
|
|
|
user = create(:user)
|
|
|
|
found_user = User.identify(user.email)
|
|
|
|
expect(found_user).to be_an(User)
|
|
|
|
expect(found_user.id).to eq user.id
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context '.authenticate' do
|
|
|
|
|
|
|
|
it 'authenticates by username and password' do
|
2018-03-28 05:33:41 +00:00
|
|
|
password = 'zammad'
|
|
|
|
user = create(:user, password: password)
|
|
|
|
result = described_class.authenticate(user.login, password)
|
2017-04-19 10:09:54 +00:00
|
|
|
expect(result).to be_an(User)
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'failure' do
|
|
|
|
|
|
|
|
it 'increases login_failed on failed logins' do
|
|
|
|
user = create(:user)
|
|
|
|
expect do
|
|
|
|
described_class.authenticate(user.login, 'wrongpw')
|
|
|
|
user.reload
|
|
|
|
end
|
|
|
|
.to change { user.login_failed }.by(1)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'fails for unknown users' do
|
|
|
|
result = described_class.authenticate('john.doe', 'zammad')
|
|
|
|
expect(result).to be nil
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'fails for inactive users' do
|
|
|
|
user = create(:user, active: false)
|
|
|
|
result = described_class.authenticate(user.login, 'zammad')
|
|
|
|
expect(result).to be nil
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'fails for users with too many failed logins' do
|
|
|
|
user = create(:user, login_failed: 999)
|
|
|
|
result = described_class.authenticate(user.login, 'zammad')
|
|
|
|
expect(result).to be nil
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'fails for wrong passwords' do
|
|
|
|
user = create(:user)
|
|
|
|
result = described_class.authenticate(user.login, 'wrongpw')
|
|
|
|
expect(result).to be nil
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'fails for empty username parameter' do
|
|
|
|
result = described_class.authenticate('', 'zammad')
|
|
|
|
expect(result).to be nil
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'fails for empty password parameter' do
|
|
|
|
result = described_class.authenticate('username', '')
|
|
|
|
expect(result).to be nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-03-27 13:22:07 +00:00
|
|
|
context '#by_reset_token' do
|
2017-02-24 17:27:27 +00:00
|
|
|
|
|
|
|
it 'returns a User instance for existing tokens' do
|
|
|
|
token = create(:token_password_reset)
|
|
|
|
expect(described_class.by_reset_token(token.name)).to be_instance_of(described_class)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'returns nil for not existing tokens' do
|
|
|
|
expect(described_class.by_reset_token('not-existing')).to be nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-03-28 05:33:41 +00:00
|
|
|
context '#password_reset_via_token' do
|
2017-02-24 17:27:27 +00:00
|
|
|
|
|
|
|
it 'changes the password of the token user and destroys the token' do
|
|
|
|
token = create(:token_password_reset)
|
|
|
|
user = User.find(token.user_id)
|
|
|
|
|
2017-10-01 12:25:52 +00:00
|
|
|
expect do
|
2017-02-24 17:27:27 +00:00
|
|
|
described_class.password_reset_via_token(token.name, new_password)
|
|
|
|
user.reload
|
2017-10-01 12:25:52 +00:00
|
|
|
end.to change {
|
2017-02-24 17:27:27 +00:00
|
|
|
user.password
|
|
|
|
}.and change {
|
|
|
|
Token.count
|
|
|
|
}.by(-1)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-03-27 13:22:07 +00:00
|
|
|
context 'import' do
|
|
|
|
|
|
|
|
it "doesn't change imported passwords" do
|
|
|
|
|
|
|
|
# mock settings calls
|
|
|
|
expect(Setting).to receive(:get).with('import_mode').and_return(true)
|
|
|
|
allow(Setting).to receive(:get)
|
|
|
|
|
|
|
|
user = build(:user, password: '{sha2}dd9c764fa7ea18cd992c8600006d3dc3ac983d1ba22e9ba2d71f6207456be0ba') # zammad
|
2017-10-01 12:25:52 +00:00
|
|
|
expect do
|
2017-03-27 13:22:07 +00:00
|
|
|
user.save
|
2017-10-01 12:25:52 +00:00
|
|
|
end.to_not change {
|
2017-03-27 13:22:07 +00:00
|
|
|
user.password
|
|
|
|
}
|
|
|
|
end
|
|
|
|
end
|
2018-03-28 05:33:41 +00:00
|
|
|
|
|
|
|
context '.access?' do
|
|
|
|
|
|
|
|
let(:role_with_admin_user_permissions) do
|
|
|
|
create(:role).tap do |role|
|
|
|
|
role.permission_grant('admin.user')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
let(:admin_with_admin_user_permissions) { create(:user, roles: [role_with_admin_user_permissions]) }
|
|
|
|
|
|
|
|
let(:role_without_admin_user_permissions) do
|
|
|
|
create(:role).tap do |role|
|
|
|
|
role.permission_grant('admin.tag')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
let(:admin_without_admin_user_permissions) { create(:user, roles: [role_without_admin_user_permissions]) }
|
|
|
|
|
|
|
|
context 'read' do
|
|
|
|
|
|
|
|
context 'admin' do
|
|
|
|
|
|
|
|
let(:requested) { create(:admin_user) }
|
|
|
|
|
|
|
|
it 'is possible for admin.user' do
|
|
|
|
requester = admin_with_admin_user_permissions
|
|
|
|
access = requested.access?(requester, 'read')
|
|
|
|
expect(access).to be(true)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'is possible for sub admin without admin.user' do
|
|
|
|
requester = admin_without_admin_user_permissions
|
|
|
|
access = requested.access?(requester, 'read')
|
|
|
|
expect(access).to be(true)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'is possible for agent' do
|
|
|
|
requester = create(:agent_user)
|
|
|
|
access = requested.access?(requester, 'read')
|
|
|
|
expect(access).to be(true)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'is not possible for customer' do
|
|
|
|
requester = create(:customer_user)
|
|
|
|
access = requested.access?(requester, 'read')
|
|
|
|
expect(access).to be(false)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'agent' do
|
|
|
|
|
|
|
|
let(:requested) { create(:agent_user) }
|
|
|
|
|
|
|
|
it 'is possible for admin.user' do
|
|
|
|
requester = admin_with_admin_user_permissions
|
|
|
|
access = requested.access?(requester, 'read')
|
|
|
|
expect(access).to be(true)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'is possible for sub admin without admin.user' do
|
|
|
|
requester = admin_without_admin_user_permissions
|
|
|
|
access = requested.access?(requester, 'read')
|
|
|
|
expect(access).to be(true)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'is possible for agent' do
|
|
|
|
requester = create(:agent_user)
|
|
|
|
access = requested.access?(requester, 'read')
|
|
|
|
expect(access).to be(true)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'is not possible for customer' do
|
|
|
|
requester = create(:customer_user)
|
|
|
|
access = requested.access?(requester, 'read')
|
|
|
|
expect(access).to be(false)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'customer' do
|
|
|
|
|
|
|
|
let(:requested) { create(:customer_user) }
|
|
|
|
|
|
|
|
it 'is possible for admin.user' do
|
|
|
|
requester = admin_with_admin_user_permissions
|
|
|
|
access = requested.access?(requester, 'read')
|
|
|
|
expect(access).to be(true)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'is possible for sub admin without admin.user' do
|
|
|
|
requester = admin_without_admin_user_permissions
|
|
|
|
access = requested.access?(requester, 'read')
|
|
|
|
expect(access).to be(true)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'is possible for agent' do
|
|
|
|
requester = create(:agent_user)
|
|
|
|
access = requested.access?(requester, 'read')
|
|
|
|
expect(access).to be(true)
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'is possible for same customer' do
|
|
|
|
access = requested.access?(requested, 'read')
|
|
|
|
expect(access).to be(true)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'is possible for same organization' do
|
|
|
|
organization = create(:organization)
|
|
|
|
requester = create(:customer_user, organization: organization)
|
|
|
|
requested.update!(organization: organization)
|
|
|
|
access = requested.access?(requester, 'read')
|
|
|
|
expect(access).to be(true)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'is not possible for different customer' do
|
|
|
|
requester = create(:customer_user)
|
|
|
|
access = requested.access?(requester, 'read')
|
|
|
|
expect(access).to be(false)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'change' do
|
|
|
|
|
|
|
|
context 'admin' do
|
|
|
|
|
|
|
|
let(:requested) { create(:admin_user) }
|
|
|
|
|
|
|
|
it 'is possible for admin.user' do
|
|
|
|
requester = admin_with_admin_user_permissions
|
|
|
|
access = requested.access?(requester, 'change')
|
|
|
|
expect(access).to be(true)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'is not possible for sub admin without admin.user' do
|
|
|
|
requester = admin_without_admin_user_permissions
|
|
|
|
access = requested.access?(requester, 'change')
|
|
|
|
expect(access).to be(false)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'is not possible for same for sub admin without admin.user' do
|
|
|
|
access = admin_without_admin_user_permissions.access?(admin_without_admin_user_permissions, 'change')
|
|
|
|
expect(access).to be(false)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'is not possible for agent' do
|
|
|
|
requester = create(:agent_user)
|
|
|
|
access = requested.access?(requester, 'change')
|
|
|
|
expect(access).to be(false)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'is not possible for customer' do
|
|
|
|
requester = create(:customer_user)
|
|
|
|
access = requested.access?(requester, 'change')
|
|
|
|
expect(access).to be(false)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'agent' do
|
|
|
|
|
|
|
|
let(:requested) { create(:agent_user) }
|
|
|
|
|
|
|
|
it 'is possible for admin.user' do
|
|
|
|
requester = admin_with_admin_user_permissions
|
|
|
|
access = requested.access?(requester, 'change')
|
|
|
|
expect(access).to be(true)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'is not possible for sub admin without admin.user' do
|
|
|
|
requester = admin_without_admin_user_permissions
|
|
|
|
access = requested.access?(requester, 'change')
|
|
|
|
expect(access).to be(false)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'is not possible for same agent' do
|
|
|
|
access = requested.access?(requested, 'change')
|
|
|
|
expect(access).to be(false)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'is not possible for other agent' do
|
|
|
|
requester = create(:agent_user)
|
|
|
|
access = requested.access?(requester, 'change')
|
|
|
|
expect(access).to be(false)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'is not possible for customer' do
|
|
|
|
requester = create(:customer_user)
|
|
|
|
access = requested.access?(requester, 'change')
|
|
|
|
expect(access).to be(false)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'customer' do
|
|
|
|
|
|
|
|
let(:requested) { create(:customer_user) }
|
|
|
|
|
|
|
|
it 'is possible for admin.user' do
|
|
|
|
requester = admin_with_admin_user_permissions
|
|
|
|
access = requested.access?(requester, 'change')
|
|
|
|
expect(access).to be(true)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'is not possible for sub admin without admin.user' do
|
|
|
|
requester = admin_without_admin_user_permissions
|
|
|
|
access = requested.access?(requester, 'change')
|
|
|
|
expect(access).to be(false)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'is possible for agent' do
|
|
|
|
requester = create(:agent_user)
|
|
|
|
access = requested.access?(requester, 'change')
|
|
|
|
expect(access).to be(true)
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'is not possible for same customer' do
|
|
|
|
access = requested.access?(requested, 'change')
|
|
|
|
expect(access).to be(false)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'is not possible for same organization' do
|
|
|
|
organization = create(:organization)
|
|
|
|
requester = create(:customer_user, organization: organization)
|
|
|
|
requested.update!(organization: organization)
|
|
|
|
access = requested.access?(requester, 'change')
|
|
|
|
expect(access).to be(false)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'is not possible for different customer' do
|
|
|
|
requester = create(:customer_user)
|
|
|
|
access = requested.access?(requester, 'change')
|
|
|
|
expect(access).to be(false)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'delete' do
|
|
|
|
|
|
|
|
context 'admin' do
|
|
|
|
|
|
|
|
let(:requested) { create(:admin_user) }
|
|
|
|
|
|
|
|
it 'is possible for admin.user' do
|
|
|
|
requester = admin_with_admin_user_permissions
|
|
|
|
access = requested.access?(requester, 'delete')
|
|
|
|
expect(access).to be(true)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'is not possible for sub admin without admin.user' do
|
|
|
|
requester = admin_without_admin_user_permissions
|
|
|
|
access = requested.access?(requester, 'delete')
|
|
|
|
expect(access).to be(false)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'is not possible for agent' do
|
|
|
|
requester = create(:agent_user)
|
|
|
|
access = requested.access?(requester, 'delete')
|
|
|
|
expect(access).to be(false)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'is not possible for customer' do
|
|
|
|
requester = create(:customer_user)
|
|
|
|
access = requested.access?(requester, 'delete')
|
|
|
|
expect(access).to be(false)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'agent' do
|
|
|
|
|
|
|
|
let(:requested) { create(:agent_user) }
|
|
|
|
|
|
|
|
it 'is possible for admin.user' do
|
|
|
|
requester = admin_with_admin_user_permissions
|
|
|
|
access = requested.access?(requester, 'delete')
|
|
|
|
expect(access).to be(true)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'is not possible for sub admin without admin.user' do
|
|
|
|
requester = admin_without_admin_user_permissions
|
|
|
|
access = requested.access?(requester, 'delete')
|
|
|
|
expect(access).to be(false)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'is not possible for agent' do
|
|
|
|
requester = create(:agent_user)
|
|
|
|
access = requested.access?(requester, 'delete')
|
|
|
|
expect(access).to be(false)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'is not possible for customer' do
|
|
|
|
requester = create(:customer_user)
|
|
|
|
access = requested.access?(requester, 'delete')
|
|
|
|
expect(access).to be(false)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'customer' do
|
|
|
|
|
|
|
|
let(:requested) { create(:customer_user) }
|
|
|
|
|
|
|
|
it 'is possible for admin.user' do
|
|
|
|
requester = admin_with_admin_user_permissions
|
|
|
|
access = requested.access?(requester, 'delete')
|
|
|
|
expect(access).to be(true)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'is not possible for sub admin without admin.user' do
|
|
|
|
requester = admin_without_admin_user_permissions
|
|
|
|
access = requested.access?(requester, 'delete')
|
|
|
|
expect(access).to be(false)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'is not possible for agent' do
|
|
|
|
requester = create(:agent_user)
|
|
|
|
access = requested.access?(requester, 'delete')
|
|
|
|
expect(access).to be(false)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'is not possible for same customer' do
|
|
|
|
access = requested.access?(requested, 'delete')
|
|
|
|
expect(access).to be(false)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'is not possible for same organization' do
|
|
|
|
organization = create(:organization)
|
|
|
|
requester = create(:customer_user, organization: organization)
|
|
|
|
requested.update!(organization: organization)
|
|
|
|
access = requested.access?(requester, 'delete')
|
|
|
|
expect(access).to be(false)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'is not possible for different customer' do
|
|
|
|
requester = create(:customer_user)
|
|
|
|
access = requested.access?(requester, 'delete')
|
|
|
|
expect(access).to be(false)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2018-06-22 17:42:28 +00:00
|
|
|
|
|
|
|
context 'agent limit' do
|
|
|
|
|
|
|
|
def current_agent_count
|
|
|
|
User.with_permissions('ticket.agent').count
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:agent_role) { Role.lookup(name: 'Agent') }
|
|
|
|
let(:admin_role) { Role.lookup(name: 'Admin') }
|
|
|
|
|
|
|
|
context '#validate_agent_limit_by_role' do
|
|
|
|
|
|
|
|
context 'agent creation limit not reached' do
|
|
|
|
|
|
|
|
it 'grants agent creation' do
|
|
|
|
Setting.set('system_agent_limit', current_agent_count + 1)
|
|
|
|
|
|
|
|
expect do
|
|
|
|
create(:agent_user)
|
|
|
|
end.to change {
|
|
|
|
current_agent_count
|
|
|
|
}.by(1)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'grants role change' do
|
|
|
|
Setting.set('system_agent_limit', current_agent_count + 1)
|
|
|
|
|
|
|
|
future_agent = create(:customer_user)
|
|
|
|
|
|
|
|
expect do
|
|
|
|
future_agent.roles = [agent_role]
|
|
|
|
end.to change {
|
|
|
|
current_agent_count
|
|
|
|
}.by(1)
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'role updates' do
|
|
|
|
|
|
|
|
it 'grants update by instances' do
|
|
|
|
Setting.set('system_agent_limit', current_agent_count + 1)
|
|
|
|
|
|
|
|
agent = create(:agent_user)
|
|
|
|
|
|
|
|
expect do
|
|
|
|
agent.roles = [
|
|
|
|
admin_role,
|
|
|
|
agent_role
|
|
|
|
]
|
|
|
|
agent.save!
|
|
|
|
end.not_to raise_error
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'grants update by id (Integer)' do
|
|
|
|
Setting.set('system_agent_limit', current_agent_count + 1)
|
|
|
|
|
|
|
|
agent = create(:agent_user)
|
|
|
|
|
|
|
|
expect do
|
|
|
|
agent.role_ids = [
|
|
|
|
admin_role.id,
|
|
|
|
agent_role.id
|
|
|
|
]
|
|
|
|
agent.save!
|
|
|
|
end.not_to raise_error
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'grants update by id (String)' do
|
|
|
|
Setting.set('system_agent_limit', current_agent_count + 1)
|
|
|
|
|
|
|
|
agent = create(:agent_user)
|
|
|
|
|
|
|
|
expect do
|
|
|
|
agent.role_ids = [
|
|
|
|
admin_role.id.to_s,
|
|
|
|
agent_role.id.to_s
|
|
|
|
]
|
|
|
|
agent.save!
|
|
|
|
end.not_to raise_error
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'agent creation limit surpassing prevention' do
|
|
|
|
|
|
|
|
it 'creation of new agents' do
|
|
|
|
Setting.set('system_agent_limit', current_agent_count + 2)
|
|
|
|
|
|
|
|
create_list(:agent_user, 2)
|
|
|
|
|
|
|
|
initial_agent_count = current_agent_count
|
|
|
|
|
|
|
|
expect do
|
|
|
|
create(:agent_user)
|
|
|
|
end.to raise_error(Exceptions::UnprocessableEntity)
|
|
|
|
|
|
|
|
expect(current_agent_count).to eq(initial_agent_count)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'prevents role change' do
|
|
|
|
Setting.set('system_agent_limit', current_agent_count)
|
|
|
|
|
|
|
|
future_agent = create(:customer_user)
|
|
|
|
|
|
|
|
initial_agent_count = current_agent_count
|
|
|
|
|
|
|
|
expect do
|
|
|
|
future_agent.roles = [agent_role]
|
|
|
|
end.to raise_error(Exceptions::UnprocessableEntity)
|
|
|
|
|
|
|
|
expect(current_agent_count).to eq(initial_agent_count)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context '#validate_agent_limit_by_attributes' do
|
|
|
|
|
|
|
|
context 'agent creation limit surpassing prevention' do
|
|
|
|
|
|
|
|
it 'prevents re-activation of agents' do
|
|
|
|
Setting.set('system_agent_limit', current_agent_count)
|
|
|
|
|
|
|
|
inactive_agent = create(:agent_user, active: false)
|
|
|
|
|
|
|
|
initial_agent_count = current_agent_count
|
|
|
|
|
|
|
|
expect do
|
|
|
|
inactive_agent.update!(active: true)
|
|
|
|
end.to raise_error(Exceptions::UnprocessableEntity)
|
|
|
|
|
|
|
|
expect(current_agent_count).to eq(initial_agent_count)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2018-07-23 08:28:21 +00:00
|
|
|
|
|
|
|
context 'when phone attribute' do
|
|
|
|
let(:user_attrs) { { phone: orig_number } }
|
|
|
|
|
|
|
|
context 'included on create' do
|
|
|
|
let(:orig_number) { '1234567890' }
|
|
|
|
|
|
|
|
it 'adds corresponding CallerId record' do
|
|
|
|
expect { subject }
|
|
|
|
.to change { Cti::CallerId.where(caller_id: orig_number).count }.by(1)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'added on update' do
|
|
|
|
let(:orig_number) { nil }
|
|
|
|
let(:new_number) { '1234567890' }
|
|
|
|
|
|
|
|
before { subject } # create user
|
|
|
|
|
|
|
|
it 'adds corresponding CallerId record' do
|
|
|
|
expect { subject.update(phone: new_number) }
|
|
|
|
.to change { Cti::CallerId.where(caller_id: new_number).count }.by(1)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-07-23 09:53:51 +00:00
|
|
|
context 'falsely added on update (change: [nil, ""])' do
|
|
|
|
let(:orig_number) { nil }
|
|
|
|
let(:new_number) { '' }
|
|
|
|
|
|
|
|
before { subject } # create user
|
|
|
|
|
|
|
|
it 'does not attempt to update CallerId record' do
|
|
|
|
allow(Cti::CallerId).to receive(:build).with(any_args)
|
|
|
|
|
|
|
|
expect(Cti::CallerId.where(object: 'User', o_id: subject.id).count)
|
|
|
|
.to eq(0)
|
|
|
|
|
|
|
|
expect { subject.update(phone: new_number) }
|
|
|
|
.to change { Cti::CallerId.where(object: 'User', o_id: subject.id).count }.by(0)
|
|
|
|
|
|
|
|
expect(Cti::CallerId).not_to have_received(:build)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-07-23 08:28:21 +00:00
|
|
|
context 'removed on update' do
|
|
|
|
let(:orig_number) { '1234567890' }
|
|
|
|
let(:new_number) { nil }
|
|
|
|
|
|
|
|
before { subject } # create user
|
|
|
|
|
|
|
|
it 'removes corresponding CallerId record' do
|
|
|
|
expect { subject.update(phone: nil) }
|
|
|
|
.to change { Cti::CallerId.where(caller_id: orig_number).count }.by(-1)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'changed on update' do
|
|
|
|
let(:orig_number) { '1234567890' }
|
|
|
|
let(:new_number) { orig_number.next }
|
|
|
|
|
|
|
|
before { subject } # create user
|
|
|
|
|
|
|
|
it 'replaces CallerId record' do
|
|
|
|
# rubocop:disable Layout/MultilineMethodCallIndentation
|
|
|
|
expect { subject.update(phone: new_number) }
|
|
|
|
.to change { Cti::CallerId.where(caller_id: orig_number).count }.by(-1)
|
|
|
|
.and change { Cti::CallerId.where(caller_id: new_number).count }.by(1)
|
|
|
|
# rubocop:enable Layout/MultilineMethodCallIndentation
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2017-02-24 17:27:27 +00:00
|
|
|
end
|