diff --git a/app/assets/javascripts/app/controllers/_ui_element/user_permission.coffee b/app/assets/javascripts/app/controllers/_ui_element/user_permission.coffee index 0d2d051e6..988024155 100644 --- a/app/assets/javascripts/app/controllers/_ui_element/user_permission.coffee +++ b/app/assets/javascripts/app/controllers/_ui_element/user_permission.coffee @@ -80,6 +80,21 @@ class App.UiElement.user_permission groupAccesses: App.Group.accesses() ) ) + throttled = _.throttle( (e) -> + input = $(@).find('input') + upcoming_state = !input.prop('checked') + value = input.val() + console.log(upcoming_state) + console.log(value) + + if value is 'full' and upcoming_state is true + $(@).closest('tr').find('input:not([value=full])').prop('checked', false) + else if value isnt 'full' and upcoming_state is true + $(@).closest('tr').find('input[value=full]').prop('checked', false) + , 300, { trailing: false }) + + item.on('click', '.checkbox-replacement', throttled) + # if customer, remove admin and agent item.find('[name=role_ids]').bind('change', (e) -> element = $(e.currentTarget) diff --git a/app/assets/javascripts/app/controllers/ticket_overview.coffee b/app/assets/javascripts/app/controllers/ticket_overview.coffee index 4e70e80a4..66f654c0a 100644 --- a/app/assets/javascripts/app/controllers/ticket_overview.coffee +++ b/app/assets/javascripts/app/controllers/ticket_overview.coffee @@ -415,7 +415,7 @@ class App.TicketOverview extends App.Controller group = App.Group.find(groupId) users = [] - for user_id in group.user_ids + for user_id in _.uniq(group.user_ids) if App.User.exists(user_id) user = App.User.find(user_id) if user.active is true @@ -620,7 +620,7 @@ class App.TicketOverview extends App.Controller users.push user for group in groups valid_user_ids = [] - for user_id in group.user_ids + for user_id in _.uniq(group.user_ids) if App.User.exists(user_id) if App.User.find(user_id).active is true valid_user_ids.push user_id diff --git a/app/assets/javascripts/app/controllers/users.coffee b/app/assets/javascripts/app/controllers/users.coffee index 27b464580..16d4a7132 100644 --- a/app/assets/javascripts/app/controllers/users.coffee +++ b/app/assets/javascripts/app/controllers/users.coffee @@ -90,6 +90,7 @@ class Index extends App.ControllerSubContent item = App.User.find(id) rerender = => + App.Group.fetch() @renderResult(user_ids) new App.ControllerGenericEdit( diff --git a/app/models/user.rb b/app/models/user.rb index a6924976d..3eb62b450 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -817,8 +817,6 @@ returns true end - private - def cache_delete super @@ -831,6 +829,8 @@ returns Cache.delete(key) end + private + def check_name if firstname.present? firstname.strip! diff --git a/app/models/user_group.rb b/app/models/user_group.rb index 795051803..d7419c2da 100644 --- a/app/models/user_group.rb +++ b/app/models/user_group.rb @@ -10,4 +10,32 @@ class UserGroup < ApplicationModel def self.ref_key :user_id end + + def cache_update + group.cache_update(nil) + user.cache_update(nil) + super + end + + def cache_delete + group.cache_update(nil) + user.cache_update(nil) + super + end + + private + + def validate_access + query = self.class.where(group: group, user: user) + + query = if access == 'full' + query.where.not(access: 'full') + else + query.where(access: 'full') + end + + errors.add(:access, 'User can have full or granular access to group') if query.exists? + end + + validate :validate_access end diff --git a/script/build/test_slice_tests.sh b/script/build/test_slice_tests.sh index c5d6b8df4..08c5ff28e 100755 --- a/script/build/test_slice_tests.sh +++ b/script/build/test_slice_tests.sh @@ -16,9 +16,11 @@ if [ "$LEVEL" == '1' ]; then rm test/browser/abb_one_group_test.rb rm test/browser/admin_channel_email_test.rb rm test/browser/admin_calendar_sla_test.rb + rm test/browser/admin_drag_drop_to_new_group_test.rb rm test/browser/admin_object_manager_test.rb rm test/browser/admin_object_manager_tree_select_test.rb rm test/browser/admin_overview_test.rb + rm test/browser/admin_permissions_granular_vs_full_test.rb rm test/browser/admin_role_test.rb # test/browser/agent_navigation_and_title_test.rb # test/browser/agent_organization_profile_test.rb @@ -86,9 +88,11 @@ elif [ "$LEVEL" == '2' ]; then # test/browser/abb_one_group_test.rb rm test/browser/admin_channel_email_test.rb rm test/browser/admin_calendar_sla_test.rb + rm test/browser/admin_drag_drop_to_new_group_test.rb rm test/browser/admin_object_manager_test.rb rm test/browser/admin_object_manager_tree_select_test.rb rm test/browser/admin_overview_test.rb + rm test/browser/admin_permissions_granular_vs_full_test.rb #rm test/browser/admin_role_test.rb rm test/browser/agent_navigation_and_title_test.rb rm test/browser/agent_organization_profile_test.rb @@ -156,9 +160,11 @@ elif [ "$LEVEL" == '3' ]; then # test/browser/abb_one_group_test.rb rm test/browser/admin_channel_email_test.rb rm test/browser/admin_calendar_sla_test.rb + rm test/browser/admin_drag_drop_to_new_group_test.rb rm test/browser/admin_object_manager_test.rb rm test/browser/admin_object_manager_tree_select_test.rb rm test/browser/admin_overview_test.rb + rm test/browser/admin_permissions_granular_vs_full_test.rb rm test/browser/admin_role_test.rb rm test/browser/agent_navigation_and_title_test.rb rm test/browser/agent_organization_profile_test.rb @@ -226,9 +232,11 @@ elif [ "$LEVEL" == '4' ]; then # test/browser/abb_one_group_test.rb rm test/browser/admin_channel_email_test.rb rm test/browser/admin_calendar_sla_test.rb + rm test/browser/admin_drag_drop_to_new_group_test.rb rm test/browser/admin_object_manager_test.rb rm test/browser/admin_object_manager_tree_select_test.rb rm test/browser/admin_overview_test.rb + rm test/browser/admin_permissions_granular_vs_full_test.rb rm test/browser/admin_role_test.rb rm test/browser/agent_navigation_and_title_test.rb rm test/browser/agent_organization_profile_test.rb @@ -295,9 +303,11 @@ elif [ "$LEVEL" == '5' ]; then # test/browser/abb_one_group_test.rb # test/browser/admin_channel_email_test.rb # test/browser/admin_calendar_sla_test.rb + # rm test/browser/admin_drag_drop_to_new_group_test.rb # test/browser/admin_object_manager_test.rb # test/browser/admin_object_manager_tree_select_test.rb # test/browser/admin_overview_test.rb + # rm test/browser/admin_permissions_granular_vs_full_test.rb rm test/browser/admin_role_test.rb rm test/browser/agent_navigation_and_title_test.rb rm test/browser/agent_organization_profile_test.rb @@ -367,9 +377,11 @@ elif [ "$LEVEL" == '6' ]; then rm test/browser/abb_one_group_test.rb rm test/browser/admin_channel_email_test.rb rm test/browser/admin_calendar_sla_test.rb + rm test/browser/admin_drag_drop_to_new_group_test.rb rm test/browser/admin_object_manager_test.rb rm test/browser/admin_object_manager_tree_select_test.rb rm test/browser/admin_overview_test.rb + rm test/browser/admin_permissions_granular_vs_full_test.rb rm test/browser/admin_role_test.rb rm test/browser/agent_navigation_and_title_test.rb rm test/browser/agent_organization_profile_test.rb diff --git a/test/browser/admin_drag_drop_to_new_group_test.rb b/test/browser/admin_drag_drop_to_new_group_test.rb new file mode 100644 index 000000000..bc6900a50 --- /dev/null +++ b/test/browser/admin_drag_drop_to_new_group_test.rb @@ -0,0 +1,93 @@ +require 'browser_test_helper' + +class AdminDragDropToNewGroupTest < TestCase + def test_new_group + new_group_name = "d_n_d_group#{rand(99_999_999)}" + @browser = browser_instance + login( + username: 'master@example.com', + password: 'test', + url: browser_url, + ) + tasks_close_all() + + click(css: '.user-menu a[title=Admin') + click(css: '.content.active a[href="#manage/groups"]') + click(css: '.content.active a[data-type="new"]') + + modal_ready + + element = @browser.find_element(css: '.modal input[name=name]') + element.clear + element.send_keys(new_group_name) + click(css: '.modal button.js-submit') + + sleep(1) + + click(css: '.content.active a[href="#manage/users"]') + + user_css = '.user-list .js-tableBody tr td' + watch_for(css: user_css) + click(css: user_css) + + modal_ready + + scroll_script = "var el = document.getElementsByClassName('modal')[0];" + scroll_script += 'el.scrollTo(0, el.scrollHeight);' + + @browser.execute_script scroll_script + + group = @browser.find_elements(css: '.modal .settings-list tbody tr').find do |el| + el.find_element(css: 'td').text == new_group_name + end + + assert_not_nil(group) + + %w[read create].each { |val| toggle_checkbox(group, val) } + + click(css: '.modal button.js-submit') + + sleep(1) + + click(css: '.menu-item[href="#ticket/view"]') + click(css: '.overview-header .tabsHolder a.tab[href="#ticket/view/all_unassigned"]') + + element = @browser.find_element(css: '.js-tableBody .item') + + @browser + .action + .click_and_hold(element) + .move_by(100, 100) + .perform + + sleep(1) + + @browser + .action + .move_to(@browser.find_element(css: '.js-batch-assign-circle')) + .perform + + sleep(1) + + group_containers = @browser.find_elements(css: '.batch-overlay-assign-entry[data-action=group_assign]') + + new_group_container = group_containers.find do |g| + g.find_element(css: '.batch-overlay-assign-entry-name').text.downcase == new_group_name + end + + assert_not_nil new_group_container + + group_description = new_group_container.find_element(css: '.batch-overlay-assign-entry-detail').text + assert_equal('1 PEOPLE', group_description) + + @browser + .action + .move_to(new_group_container) + .perform + + sleep(1) + + users_in_group = @browser.find_elements(css: '.js-batch-assign-group-inner .batch-overlay-assign-entry[data-action=user_assign]') + assert_equal(1, users_in_group.count) + end +end diff --git a/test/browser/admin_permissions_granular_vs_full_test.rb b/test/browser/admin_permissions_granular_vs_full_test.rb new file mode 100644 index 000000000..688698edc --- /dev/null +++ b/test/browser/admin_permissions_granular_vs_full_test.rb @@ -0,0 +1,58 @@ +require 'browser_test_helper' + +class AdminPermissionsGranularVsFullTest < TestCase + def test_permissions_selecting + new_group_name = "permissions_test_group#{rand(99_999_999)}" + @browser = browser_instance + login( + username: 'master@example.com', + password: 'test', + url: browser_url, + ) + tasks_close_all() + + click(css: '.user-menu a[title=Admin') + click(css: '.content.active a[href="#manage/groups"]') + click(css: '.content.active a[data-type="new"]') + + modal_ready + + element = @browser.find_element(css: '.modal input[name=name]') + element.clear + element.send_keys(new_group_name) + click(css: '.modal button.js-submit') + + sleep(1) + + click(css: '.content.active a[href="#manage/users"]') + + user_css = '.user-list .js-tableBody tr td' + watch_for(css: user_css) + click(css: user_css) + + modal_ready + + scroll_script = "var el = document.getElementsByClassName('modal')[0];" + scroll_script += 'el.scrollTo(0, el.scrollHeight);' + + @browser.execute_script scroll_script + + group = @browser.find_elements(css: '.modal .settings-list tbody tr').find do |el| + el.find_element(css: 'td').text == new_group_name + end + + toggle_checkbox(group, 'full') + sleep(1) + assert(checkbox_is_selected(group, 'full')) + + toggle_checkbox(group, 'read') + sleep(1) + assert(!checkbox_is_selected(group, 'full')) + assert(checkbox_is_selected(group, 'read')) + + toggle_checkbox(group, 'full') + sleep(1) + assert(checkbox_is_selected(group, 'full')) + assert(!checkbox_is_selected(group, 'read')) + end +end diff --git a/test/browser_test_helper.rb b/test/browser_test_helper.rb index 6d854669a..2141e3020 100644 --- a/test/browser_test_helper.rb +++ b/test/browser_test_helper.rb @@ -3871,4 +3871,18 @@ wait untill text in selector disabppears container: original_element ) end + + def toggle_checkbox(scope, value) + checkbox = scope.find_element(css: "input[value=#{value}]") + + @browser + .action + .move_to(checkbox) + .click + .perform + end + + def checkbox_is_selected(scope, value) + scope.find_element(css: "input[value=#{value}]").property('checked') + end end diff --git a/test/unit/user_group_test.rb b/test/unit/user_group_test.rb new file mode 100644 index 000000000..d7a98fc92 --- /dev/null +++ b/test/unit/user_group_test.rb @@ -0,0 +1,44 @@ +require 'test_helper' + +class UserGroupTest < ActiveSupport::TestCase + test 'user group permissions' do + rand = rand(9_999_999_999) + agent1 = User.create!( + login: "agent-permission-check#{rand}@example.com", + firstname: 'vaild_agent_group_permission-1', + lastname: 'Agent', + email: "agent-permission-check#{rand}@example.com", + password: 'agentpw', + active: true, + roles: Role.where(name: 'Agent'), + groups: Group.all, + updated_by_id: 1, + created_by_id: 1, + ) + + group1 = Group.create!( + name: "GroupPermissionsTest-#{rand(9_999_999_999)}", + active: true, + updated_by_id: 1, + created_by_id: 1, + ) + + assert_nothing_raised do + UserGroup.create!(user: agent1, group: group1, access: 'full') + end + + assert_raises do + UserGroup.create!(user: agent1, group: group1, access: 'read') + end + + UserGroup.where(user: agent1, group: group1).destroy_all + + assert_nothing_raised do + UserGroup.create!(user: agent1, group: group1, access: 'read') + end + + assert_raises do + UserGroup.create!(user: agent1, group: group1, access: 'full') + end + end +end diff --git a/test/unit/user_test.rb b/test/unit/user_test.rb index 3eda56389..7c0fbfcdf 100644 --- a/test/unit/user_test.rb +++ b/test/unit/user_test.rb @@ -1270,4 +1270,34 @@ class UserTest < ActiveSupport::TestCase assert_equal(0, RecentView.where(created_by_id: agent1_id).count) end + test 'adding group drops cache' do + agent1 = User.create!( + login: "agent-cleanup_check-1#{name}@example.com", + firstname: 'vaild_agent_group_permission-1', + lastname: "Agent#{name}", + email: "agent-cleanup_check-1#{name}@example.com", + password: 'agentpw', + active: true, + roles: Role.where(name: 'Agent'), + groups: Group.all, + updated_by_id: 1, + created_by_id: 1, + ) + + group1 = Group.create_or_update( + name: "GroupWithoutPermission-#{rand(9_999_999_999)}", + active: true, + updated_by_id: 1, + created_by_id: 1, + ) + + differences = %w[ + group1.attributes_with_association_ids['user_ids'].count + agent1.attributes_with_association_ids['group_ids'].keys.count + ] + + assert_difference differences, 1 do + agent1.groups << group1 + end + end end