Browse Source

Fixed issue #2026 by checking for change permission before showing bulk action form (fixes #2026)

Billy Zhou 6 years ago
parent
commit
45fee1b752

+ 17 - 6
app/assets/javascripts/app/controllers/ticket_overview.coffee

@@ -1097,11 +1097,11 @@ class Table extends App.Controller
           id: object.organization_id
         value
       callbackCheckbox = (id, checked, e) =>
-        if @$('table').find('input[name="bulk"]:checked').length == 0
-          @bulkForm.hide()
-        else
+        if @shouldShowBulkForm()
           @bulkForm.render()
           @bulkForm.show()
+        else
+          @bulkForm.hide()
 
         if @lastChecked && e.shiftKey
           # check items in a row
@@ -1191,11 +1191,11 @@ class Table extends App.Controller
 
     # show/hide bulk action
     @$('.table-overview').delegate('input[name="bulk"], input[name="bulk_all"]', 'change', (e) =>
-      if @$('.table-overview').find('input[name="bulk"]:checked').length == 0
+      if @shouldShowBulkForm()
+        @bulkForm.show()
+      else
         @bulkForm.hide()
         @bulkForm.reset()
-      else
-        @bulkForm.show()
     )
 
     # deselect bulk_all if one item is uncheck observ
@@ -1215,6 +1215,17 @@ class Table extends App.Controller
           bulkAll.prop('indeterminate', true)
     )
 
+  shouldShowBulkForm: =>
+    items = @$('table').find('input[name="bulk"]:checked')
+    return false if items.length == 0
+
+    ticket_ids        = _.map(items, (el) -> $(el).val() )
+    ticket_group_ids  = _.map(App.Ticket.findAll(ticket_ids), (ticket) -> ticket.group_id)
+    ticket_group_ids  = _.uniq(ticket_group_ids)
+    user_permissions  = App.Session.get('group_ids')
+    group_permissions = ticket_group_ids.map (id) -> user_permissions[id]
+    _.every(group_permissions, (list) -> 'full' in list || 'change' in list)
+
   viewmode: (e) =>
     e.preventDefault()
     @view_mode = $(e.target).data('mode')

+ 180 - 0
test/browser/agent_ticket_overview_level0_test.rb

@@ -468,4 +468,184 @@ class AgentTicketOverviewLevel0Test < TestCase
     # cleanup
     tasks_close_all()
   end
+
+  # verify fix for issue #2026 - Bulk action should not be shown if user has no change permissions
+  def test_no_bulk_action_when_missing_change_permission
+    @browser = browser_instance
+    login(
+      username: 'master@example.com',
+      password: 'test',
+      url: browser_url,
+    )
+    tasks_close_all()
+
+    # create new group
+    group_create(
+      data: {
+        name: 'some group2',
+      },
+    )
+
+    click(
+      css: 'a[href="#manage"]',
+    )
+    click(
+      css: '.content.active a[href="#manage/groups"]',
+    )
+
+    user_edit(
+      data: {
+        login:       'master@example.com',
+        permissions: { 1 => ['full'],
+                       2 => ['full'],
+                       3 => ['full'], }
+      },
+    )
+
+    user_create(
+      data: {
+        firstname:   'Tester',
+        lastname:    'Agent 2',
+        email:       'agent2@example.com',
+        password:    'test',
+        role:        'Agent',
+        permissions: { 1 => %w[read create overview],
+                       2 => ['full'],
+                       3 => ['full'], }
+      },
+    )
+
+    # create new tickets
+    can_change_ticket = ticket_create(
+      data: {
+        customer: 'nico',
+        group: 'some group2',
+        title: 'overview test #5',
+        body: 'overview test #5',
+      }
+    )
+    cannot_change_ticket = ticket_create(
+      data: {
+        customer: 'nico',
+        group: 'Users',
+        title: 'overview test #6',
+        body: 'overview test #6',
+      }
+    )
+
+    logout() # logout as master@example.com then login as agent2@example.com
+    login(
+      username: 'agent2@example.com',
+      password: 'test',
+      url: browser_url,
+    )
+    tasks_close_all()
+
+    # open Overview menu tab
+    click(
+      css: '.js-menu .js-overviewsMenuItem',
+    )
+
+    # enable full overviews
+    execute(
+      js: '$(".content.active .sidebar").css("display", "block")',
+    )
+
+    # click Unassigned & Open tab
+    click(
+      css: '.content.active [href="#ticket/view/all_unassigned"]',
+    )
+
+    watch_for(
+      css: '.content.active',
+      value: 'overview test #6',
+      timeout: 8,
+    )
+
+    # first select the ticket that we have change rights to
+    check(
+      css: '.content.active table tr td input[value="' + can_change_ticket[:id] + '"]',
+    )
+
+    # check that the bulk action form appears
+    exists(
+      displayed: true,
+      css: '.content.active .bulkAction',
+    )
+
+    # then select the ticket that we do not have change rights to
+    scroll_to(
+      position: 'top',
+      css:      '.content.active table tr td input[value="' + cannot_change_ticket[:id] + '"] + .icon-checkbox.icon-unchecked',
+    )
+    check(
+      css: '.content.active table tr td input[value="' + cannot_change_ticket[:id] + '"]',
+    )
+
+    # check that the bulk action form disappears
+    exists(
+      displayed: false,
+      css: '.content.active .bulkAction',
+    )
+
+    # de-select the ticket that we do not have change rights to
+    uncheck(
+      css: '.content.active table tr td input[value="' + cannot_change_ticket[:id] + '"]',
+      fast: true,
+    )
+
+    # check that the bulk action form appears again
+    exists(
+      displayed: true,
+      css: '.content.active .bulkAction',
+    )
+
+    # de-select the ticket that we have change rights to
+    uncheck(
+      css: '.content.active table tr td input[value="' + can_change_ticket[:id] + '"]',
+      fast: true,
+    )
+
+    # check that the bulk action form disappears again
+    exists(
+      displayed: false,
+      css: '.content.active .bulkAction',
+    )
+
+    # cleanup
+    tasks_close_all()
+    logout() # logout as agent2@example.com and then login as master@example.com to clean up tickets
+    login(
+      username: 'master@example.com',
+      password: 'test',
+      url: browser_url,
+    )
+    tasks_close_all()
+
+    # open ticket by search
+    ticket_open_by_search(
+      number: cannot_change_ticket[:number],
+    )
+    sleep 1
+
+    # close ticket
+    ticket_update(
+      data: {
+        state: 'closed',
+      }
+    )
+
+    # open ticket by search
+    ticket_open_by_search(
+      number: can_change_ticket[:number],
+    )
+    sleep 1
+
+    # close ticket
+    ticket_update(
+      data: {
+        state: 'closed',
+      }
+    )
+  end
 end

+ 192 - 3
test/browser_test_helper.rb

@@ -2829,6 +2829,22 @@ wait untill text in selector disabppears
       lastname:  'Manage Lastname' + random,
       email:     user_email,
       password:  'some-pass',
+      role:      'Admin',     # optional, choose among [Admin, Agent, Customer]
+                              # defaults to Customer if not provided
+    },
+  )
+
+  user_create(
+    browser: browser2,
+    data: {
+      #login:      'some login' + random,
+      firstname:   'Manage Firstname' + random,
+      lastname:    'Manage Lastname' + random,
+      email:       user_email,
+      password:    'some-pass',
+      role:        'Agent',     # when the role is Agent an array of permissions for each group is optionally accepted
+      permissions: { 1 => %w[read create overview],
+                       2 => ['full'], }
     },
   )
 
@@ -2901,11 +2917,46 @@ wait untill text in selector disabppears
         retry if retries < 3
       end
     end
-    check(
+
+    if data[:role]
+      if data[:role] == 'Admin'
+        check(
+          browser: instance,
+          css:     '.modal input[name=role_ids][value=1]',
+        )
+      elsif data[:role] == 'Customer'
+        check(
+          browser: instance,
+          css:     '.modal input[name=role_ids][value=3]',
+        )
+      elsif data[:role] == 'Agent'
+        check(
+          browser: instance,
+          css:     '.modal input[name=role_ids][value=2]',
+        )
+        data[:permissions].each do |key, value|
+          value.each do |permission|
+            check(
+              browser: instance,
+              css:     ".modal input[name=\"group_ids::#{key}\"][value=\"#{permission}\"]",
+            )
+          end
+        end
+      else
+        raise "Unknown :role \"#{data[:role]}\" in user_create()"
+      end
+    else
+      check(
+        browser: instance,
+        css:     '.modal input[name=role_ids][value=3]',
+      )
+    end
+
+    click(
       browser: instance,
-      css:     '.modal input[name=role_ids][value=3]',
+      css:     '.modal .js-submit',
     )
-    instance.find_elements(css: '.modal button.js-submit')[0].click
+
     modal_disappear(
       browser: instance,
       timeout: 10,
@@ -2939,6 +2990,144 @@ wait untill text in selector disabppears
     assert(true, 'user created')
   end
 
+=begin
+
+  user_edit(
+    browser: browser2,
+    data: {
+      login:      'some login' + random,
+      firstname:   'Manage Firstname' + random,
+      lastname:    'Manage Lastname' + random,
+      email:       user_email,
+      password:    'some-pass',
+      role:        'Agent',     # when the role is Agent an array of permissions for each group is optionally accepted
+      permissions: { 1 => %w[read create overview],
+                       2 => ['full'], }
+    },
+  )
+
+=end
+
+  def user_edit(params = {})
+    switch_window_focus(params)
+    log('user_edit', params)
+
+    instance = params[:browser] || @browser
+    data     = params[:data]
+
+    click(
+      browser: instance,
+      css:  'a[href="#manage"]',
+      mute_log: true,
+    )
+    click(
+      browser: instance,
+      css:  '.content.active a[href="#manage/users"]',
+      mute_log: true,
+    )
+    instance.find_elements(css: '.content.active .user-list td:first-child').each do |element|
+      next if element.text.strip != data[:login]
+      element.click
+      break
+    end
+    modal_ready(browser: instance)
+    if data[:firstname]
+      element = instance.find_elements(css: '.modal input[name=firstname]')[0]
+      element.clear
+      element.send_keys(data[:firstname])
+    end
+    if data[:lastname]
+      element = instance.find_elements(css: '.modal input[name=lastname]')[0]
+      element.clear
+      element.send_keys(data[:lastname])
+    end
+    if data[:email]
+      element = instance.find_elements(css: '.modal input[name=email]')[0]
+      element.clear
+      element.send_keys(data[:email])
+    end
+    if data[:password]
+      element = instance.find_elements(css: '.modal input[name=password]')[0]
+      element.clear
+      element.send_keys(data[:password])
+      element = instance.find_elements(css: '.modal input[name=password_confirm]')[0]
+      element.clear
+      element.send_keys(data[:password])
+    end
+    if data[:phone]
+      element = instance.find_elements(css: '.modal input[name=phone]')[0]
+      element.clear
+      element.send_keys(data[:phone])
+    end
+    if data[:active].present?
+      select(css: 'select[name="active"]', value: data[:active] ? 'active' : 'inactive' )
+    end
+
+    if data[:organization]
+      element = instance.find_elements(css: '.modal input.searchableSelect-main')[0]
+      element.clear
+      element.send_keys(data[:organization])
+
+      begin
+        retries ||= 0
+        target    = nil
+        until target
+          sleep 0.5
+          target = instance.find_elements(css: ".modal li[title='#{data[:organization]}']")[0]
+        end
+        target.click()
+      rescue Selenium::WebDriver::Error::StaleElementReferenceError
+        sleep retries
+        retries += 1
+        retry if retries < 3
+      end
+    end
+
+    if data[:role]
+      if data[:role] == 'Admin'
+        check(
+          browser: instance,
+          css:     '.modal input[name=role_ids][value=1]',
+        )
+      elsif data[:role] == 'Customer'
+        check(
+          browser: instance,
+          css:     '.modal input[name=role_ids][value=3]',
+        )
+      elsif data[:role] == 'Agent'
+        check(
+          browser: instance,
+          css:     '.modal input[name=role_ids][value=2]',
+        )
+      else
+        raise "Unknown :role \"#{data[:role]}\" in user_create()"
+      end
+    end
+
+    if data[:permissions].present?
+      data[:permissions].each do |key, value|
+        value.each do |permission|
+          check(
+            browser: instance,
+            css:     ".modal input[name=\"group_ids::#{key}\"][value=\"#{permission}\"]",
+          )
+        end
+      end
+    end
+
+    click(
+      browser: instance,
+      css:     '.modal .js-submit',
+    )
+
+    modal_disappear(
+      browser: instance,
+      timeout: 10,
+    )
+
+    assert(true, 'user updated')
+  end
+
 =begin
 
   organization_create(