Merge lp:~sinzui/launchpad/unchanged-bug-supervisor into lp:launchpad

Proposed by Curtis Hovey
Status: Merged
Approved by: Robert Collins
Approved revision: no longer in the source branch.
Merged at revision: 11177
Proposed branch: lp:~sinzui/launchpad/unchanged-bug-supervisor
Merge into: lp:launchpad
Diff against target: 114 lines (+45/-7)
3 files modified
lib/lp/bugs/browser/bugrole.py (+15/-4)
lib/lp/bugs/browser/bugtarget.py (+5/-3)
lib/lp/bugs/browser/tests/test_bugtarget_configure.py (+25/-0)
To merge this branch: bzr merge lp:~sinzui/launchpad/unchanged-bug-supervisor
Reviewer Review Type Date Requested Status
Robert Collins (community) Approve
Review via email: mp+29998@code.launchpad.net

Description of the change

This is my branch to not raise a bug_supervisor field error for a no-change
event.

    lp:~sinzui/launchpad/unchanged-bug-supervisor
    Diff size: 113
    Launchpad bug:
          https://bugs.launchpad.net/bugs/605491
    Test command: ./bin/test -vv \
          -t test_bug_role_non_admin_can_edit
    Pre-implementation: deryck
    Target release: 10.08

Do not raise a bug_supervisor field error for a no-change event
----------------------------------------------------------------

I'm trying to change the bug guidelines for a project in which the supervisor
is set to a team and I'm a member for that team. Unfortunately, when a click
on 'change' I get an error because I'm trying to set supervisor to a team for
which I don't have administrator rights.

However, the bug supervisor is already set to that value, I just try to change
the bug guidelines. Is there any way to do so? Thanks.

This is a bug 1. there should be no error because there is no change. 2. in
the case of a project, the owner (any member of the owning team) must have
permission to set all fields on the project.

After talking with the bug team, the field permissions will be revised so that
they are the same, and any one who is an owner can make the change, but that
is a separate bug that requires send email. This bug is about the fact the
bug_supervisor field was not changed, there should be no error. This issue
probably affect security_contact too.

Rules
-----

    * Do not raise admin/owner errors for bug_supervisor and security_contact
      if they have not changed. This just affects the +configure-bugs.

QA
--

    * As an member of an owning team, set a team as the project bug
      supervisor using Configure bug tracker.
    * As another member of the owning team, and no an admin of the bug
      supervisor, change the bug reporting guidelines.
    * Verify that the form is saved.

Lint
----

Linting changed files:
  lib/lp/bugs/browser/bugrole.py
  lib/lp/bugs/browser/bugtarget.py
  lib/lp/bugs/browser/tests/test_bugtarget_configure.py

Test
----

    * lib/lp/bugs/browser/tests/test_bugtarget_configure.py
      * Added a test to verify a project owner who is not an admin of the
        bug_supervisor or security_contact teams can change other data in
        the form.

Implementation
--------------

    * lib/lp/bugs/browser/bugrole.py
      * Revised the validators to consider the current state of the field
        and return OK if the state has not changed. Add changeSecurityContact
        since the rule is more complex now.
    * lib/lp/bugs/browser/bugtarget.py
      * Updated the change_action to remove the security_contact from data
        as is done with bug_supervisor to avoid permission constraints.

To post a comment you must log in.
Revision history for this message
Robert Collins (lifeless) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/bugs/browser/bugrole.py'
2--- lib/lp/bugs/browser/bugrole.py 2010-06-11 21:51:48 +0000
3+++ lib/lp/bugs/browser/bugrole.py 2010-07-15 14:25:59 +0000
4@@ -20,7 +20,7 @@
5 OTHER_TEAM = object()
6 OK = object()
7
8- def _getFieldState(self, field_name, data):
9+ def _getFieldState(self, current_role, field_name, data):
10 """Return the enum that summarises the field state."""
11 # The field_name will not be in the data if the user did not enter
12 # a person in the ValidPersonOrTeam vocabulary.
13@@ -28,6 +28,10 @@
14 return self.INVALID_PERSON
15 role = data[field_name]
16 user = self.user
17+ # If no data was changed, the field is OK regardless of who the
18+ # current user is.
19+ if current_role == role:
20+ return self.OK
21 # The user may assign the role to None, himself, or a team he admins.
22 if role is None or self.context.userCanAlterSubscription(role, user):
23 return self.OK
24@@ -43,7 +47,8 @@
25 Verify that the value is None, the user, or a team he administers,
26 otherwise, set a field error.
27 """
28- field_state = self._getFieldState('bug_supervisor', data)
29+ field_state = self._getFieldState(
30+ self.context.bug_supervisor, 'bug_supervisor', data)
31 if field_state is self.INVALID_PERSON:
32 error = (
33 'You must choose a valid person or team to be the '
34@@ -78,7 +83,12 @@
35 self.setFieldError('bug_supervisor', error)
36
37 def changeBugSupervisor(self, bug_supervisor):
38- self.context.setBugSupervisor(bug_supervisor, self.user)
39+ if self.context.bug_supervisor != bug_supervisor:
40+ self.context.setBugSupervisor(bug_supervisor, self.user)
41+
42+ def changeSecurityContact(self, security_contact):
43+ if self.context.security_contact != security_contact:
44+ self.context.security_contact = security_contact
45
46 def validateSecurityContact(self, data):
47 """Validates the new security contact.
48@@ -86,7 +96,8 @@
49 Verify that the value is None, the user, or a team he administers,
50 otherwise, set a field error.
51 """
52- field_state = self._getFieldState('security_contact', data)
53+ field_state = self._getFieldState(
54+ self.context.security_contact, 'security_contact', data)
55 if field_state is self.INVALID_PERSON:
56 error = (
57 'You must choose a valid person or team to be the '
58
59=== modified file 'lib/lp/bugs/browser/bugtarget.py'
60--- lib/lp/bugs/browser/bugtarget.py 2010-06-18 00:46:17 +0000
61+++ lib/lp/bugs/browser/bugtarget.py 2010-07-15 14:25:59 +0000
62@@ -167,11 +167,13 @@
63
64 @action("Change", name='change')
65 def change_action(self, action, data):
66- # bug_supervisor requires a transition method, so it must be
67- # handled separately and removed for the updateContextFromData
68- # to work as expected.
69+ # bug_supervisor and security_contactrequires a transition method,
70+ # so it must be handled separately and removed for the
71+ # updateContextFromData to work as expected.
72 self.changeBugSupervisor(data['bug_supervisor'])
73 del data['bug_supervisor']
74+ self.changeSecurityContact(data['security_contact'])
75+ del data['security_contact']
76 self.updateContextFromData(data)
77
78
79
80=== modified file 'lib/lp/bugs/browser/tests/test_bugtarget_configure.py'
81--- lib/lp/bugs/browser/tests/test_bugtarget_configure.py 2010-06-18 00:46:17 +0000
82+++ lib/lp/bugs/browser/tests/test_bugtarget_configure.py 2010-07-15 14:25:59 +0000
83@@ -122,6 +122,31 @@
84 self.assertEqual([], view.errors)
85 self.assertFalse(self.product.enable_bug_expiration)
86
87+ def test_bug_role_non_admin_can_edit(self):
88+ # Verify that a member of an owning team who is not an admin of
89+ # the bug supervisor team or security_contact team can change bug
90+ # reporting guidelines.
91+ owning_team = self.factory.makeTeam(owner=self.owner)
92+ bug_team = self.factory.makeTeam(owner=self.owner)
93+ weak_owner = self.factory.makePerson()
94+ login_person(self.owner)
95+ owning_team.addMember(weak_owner, self.owner)
96+ bug_team.addMember(weak_owner, self.owner)
97+ self.product.owner = owning_team
98+ self.product.setBugSupervisor(bug_team, self.owner)
99+ self.product.security_contact = bug_team
100+ login_person(weak_owner)
101+ form = self._makeForm()
102+ # Only the bug_reporting_guidelines are different.
103+ form['field.bug_supervisor'] = bug_team.name
104+ form['field.security_contact'] = bug_team.name
105+ form['field.bug_reporting_guidelines'] = 'new guidelines'
106+ view = create_initialized_view(
107+ self.product, name='+configure-bugtracker', form=form)
108+ self.assertEqual([], view.errors)
109+ self.assertEqual(
110+ 'new guidelines', self.product.bug_reporting_guidelines)
111+
112
113 def test_suite():
114 return unittest.TestLoader().loadTestsFromName(__name__)