Merge lp:~stevenk/launchpad/use-userHasPriviledges into lp:launchpad

Proposed by Steve Kowalik
Status: Merged
Approved by: William Grant
Approved revision: no longer in the source branch.
Merged at revision: 14378
Proposed branch: lp:~stevenk/launchpad/use-userHasPriviledges
Merge into: lp:launchpad
Diff against target: 379 lines (+115/-42)
12 files modified
lib/lp/bugs/browser/bugtarget.py (+14/-17)
lib/lp/bugs/browser/tests/bugtarget-filebug-views.txt (+16/-11)
lib/lp/bugs/model/bugtask.py (+12/-8)
lib/lp/bugs/model/tests/test_bugtask.py (+32/-2)
lib/lp/bugs/stories/bug-release-management/xx-bug-release-management.txt (+1/-1)
lib/lp/registry/configure.zcml (+1/-0)
lib/lp/registry/interfaces/distributionsourcepackage.py (+4/-1)
lib/lp/registry/interfaces/sourcepackage.py (+6/-1)
lib/lp/registry/model/distributionsourcepackage.py (+8/-1)
lib/lp/registry/model/sourcepackage.py (+5/-0)
lib/lp/registry/tests/test_distributionsourcepackage.py (+8/-0)
lib/lp/registry/tests/test_sourcepackage.py (+8/-0)
To merge this branch: bzr merge lp:~stevenk/launchpad/use-userHasPriviledges
Reviewer Review Type Date Requested Status
William Grant (community) code Approve
Review via email: mp+82967@code.launchpad.net

Commit message

[r=wgrant][bug=885692] Add userHasPrivileges for IBugTarget contexts so that more than the bug supervisor can set the extra fields.

Description of the change

Write a class method on BugTask that checks the context (an IBugTarget) that a bug is being filed on. This allows us to extend the special rules to users such as the pillar owner or drivers.

Sadly, this branch is misnamed, and the method does not make use of IBugTask.userHasPrivilegdes() since we don't have a bugtask when the functions are called.

To post a comment you must log in.
Revision history for this message
William Grant (wgrant) :
review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/bugs/browser/bugtarget.py'
2--- lib/lp/bugs/browser/bugtarget.py 2011-11-22 23:29:08 +0000
3+++ lib/lp/bugs/browser/bugtarget.py 2011-11-24 00:54:26 +0000
4@@ -131,6 +131,7 @@
5 from lp.bugs.interfaces.bugtracker import IBugTracker
6 from lp.bugs.interfaces.malone import IMaloneApplication
7 from lp.bugs.interfaces.securitycontact import IHasSecurityContact
8+from lp.bugs.model.bugtask import BugTask
9 from lp.bugs.model.structuralsubscription import (
10 get_structural_subscriptions_for_target,
11 )
12@@ -401,11 +402,10 @@
13 # If the context is a project group we want to render the optional
14 # fields since they will initially be hidden and later exposed if the
15 # selected project supports them.
16- # XXX: StevenK 2011-11-18 bug=885692 This should make use of
17- # IBugTask.userHasPrivileges().
18 include_extra_fields = IProjectGroup.providedBy(context)
19- if not include_extra_fields and IHasBugSupervisor.providedBy(context):
20- include_extra_fields = self.user.inTeam(context.bug_supervisor)
21+ if not include_extra_fields:
22+ include_extra_fields = BugTask.userHasPrivilegesContext(
23+ context, self.user)
24
25 if include_extra_fields:
26 field_names.extend(
27@@ -628,19 +628,16 @@
28 if extra_data.private:
29 params.private = extra_data.private
30
31- # XXX: StevenK 2011-11-18 bug=885692 This should make use of
32- # IBugTask.userHasPrivileges().
33- # Apply any extra options given by a bug supervisor.
34- if IHasBugSupervisor.providedBy(context):
35- if self.user.inTeam(context.bug_supervisor):
36- if 'assignee' in data:
37- params.assignee = data['assignee']
38- if 'status' in data:
39- params.status = data['status']
40- if 'importance' in data:
41- params.importance = data['importance']
42- if 'milestone' in data:
43- params.milestone = data['milestone']
44+ # Apply any extra options given by privileged users.
45+ if BugTask.userHasPrivilegesContext(context, self.user):
46+ if 'assignee' in data:
47+ params.assignee = data['assignee']
48+ if 'status' in data:
49+ params.status = data['status']
50+ if 'importance' in data:
51+ params.importance = data['importance']
52+ if 'milestone' in data:
53+ params.milestone = data['milestone']
54
55 self.added_bug = bug = context.createBug(params)
56
57
58=== modified file 'lib/lp/bugs/browser/tests/bugtarget-filebug-views.txt'
59--- lib/lp/bugs/browser/tests/bugtarget-filebug-views.txt 2011-02-11 15:14:37 +0000
60+++ lib/lp/bugs/browser/tests/bugtarget-filebug-views.txt 2011-11-24 00:54:26 +0000
61@@ -697,23 +697,28 @@
62 True
63
64
65-Extra fields for bug supervisors
66---------------------------------
67-
68-Bug supervisors are offered several extra options when filing bugs.
69-
70- >>> person = factory.makePerson(name=u'bug-superdude')
71- >>> product = factory.makeProduct(owner=person)
72+Extra fields for privileged users
73+---------------------------------
74+
75+Privileged users are offered several extra options when filing bugs.
76+
77+ >>> owner = factory.makePerson(name=u'bug-superdude')
78+ >>> person = factory.makePerson()
79+ >>> product = factory.makeProduct(owner=owner)
80
81 >>> login_person(person)
82-
83 >>> filebug_view = create_initialized_view(product, '+filebug')
84 >>> normal_fields = set(filebug_view.field_names)
85- >>> product.setBugSupervisor(person, person)
86+ >>> login_person(owner)
87+ >>> filebug_view = create_initialized_view(product, '+filebug')
88+ >>> owner_fields = set(filebug_view.field_names)
89+ >>> product.setBugSupervisor(owner, owner)
90 >>> supervisor_fields = set(filebug_view.field_names)
91
92-Supervisors get all the same fields as normal users, plus a few extra.
93+Privileged users get all the same fields as normal users, plus a few extra.
94
95+ >>> owner_fields == supervisor_fields
96+ True
97 >>> supervisor_fields.issuperset(normal_fields)
98 True
99
100@@ -734,7 +739,7 @@
101
102 >>> bug_data = dict(
103 ... title=u'Extra Fields Bug', comment=u'Test description.',
104- ... assignee=person, importance=BugTaskImportance.HIGH,
105+ ... assignee=owner, importance=BugTaskImportance.HIGH,
106 ... milestone=milestone, status=BugTaskStatus.TRIAGED)
107 >>> print filebug_view.validate(bug_data)
108 None
109
110=== modified file 'lib/lp/bugs/model/bugtask.py'
111--- lib/lp/bugs/model/bugtask.py 2011-11-21 00:31:41 +0000
112+++ lib/lp/bugs/model/bugtask.py 2011-11-24 00:54:26 +0000
113@@ -1346,8 +1346,12 @@
114 else:
115 return None
116
117- def userHasPrivileges(self, user):
118- """See `IBugTask`."""
119+ @classmethod
120+ def userHasPrivilegesContext(cls, context, user):
121+ """Does the user have privileges for the given context?
122+
123+ :return: a boolean.
124+ """
125 if not user:
126 return False
127 role = IPersonRoles(user)
128@@ -1365,12 +1369,12 @@
129 # Otherwise, if you're a member of the pillar owner, drivers, or the
130 # bug supervisor, you can change bug details.
131 return (
132- role.isOwner(self.pillar) or role.isOneOfDrivers(self.pillar) or
133- role.isBugSupervisor(self.pillar) or
134- (self.distroseries is not None and
135- role.isDriver(self.distroseries)) or
136- (self.productseries is not None and
137- role.isDriver(self.productseries)))
138+ role.isOwner(context.pillar) or role.isOneOfDrivers(context) or
139+ role.isBugSupervisor(context.pillar))
140+
141+ def userHasPrivileges(self, user):
142+ """See `IBugTask`."""
143+ return self.userHasPrivilegesContext(self.target, user)
144
145 def __repr__(self):
146 return "<BugTask for bug %s on %r>" % (self.bugID, self.target)
147
148=== modified file 'lib/lp/bugs/model/tests/test_bugtask.py'
149--- lib/lp/bugs/model/tests/test_bugtask.py 2011-11-18 05:22:34 +0000
150+++ lib/lp/bugs/model/tests/test_bugtask.py 2011-11-24 00:54:26 +0000
151@@ -51,6 +51,7 @@
152 from lp.bugs.model.bugtask import (
153 bug_target_from_key,
154 bug_target_to_key,
155+ BugTask,
156 BugTaskSet,
157 build_tag_search_clause,
158 IllegalTarget,
159@@ -2592,12 +2593,12 @@
160 self.assertEqual([db_bug.default_bugtask], db_bug.bugtasks)
161
162
163-class TestBugTaskUserHasPriviliges(TestCaseWithFactory):
164+class TestBugTaskUserHasPrivileges(TestCaseWithFactory):
165
166 layer = DatabaseFunctionalLayer
167
168 def setUp(self):
169- super(TestBugTaskUserHasPriviliges, self).setUp()
170+ super(TestBugTaskUserHasPrivileges, self).setUp()
171 self.celebrities = getUtility(ILaunchpadCelebrities)
172
173 def test_admin_is_allowed(self):
174@@ -2655,3 +2656,32 @@
175 bugtask = self.factory.makeBugTask()
176 self.assertFalse(
177 bugtask.userHasPrivileges(self.factory.makePerson()))
178+
179+
180+class TestBugTaskUserHasPrivilegesContext(TestCaseWithFactory):
181+
182+ layer = DatabaseFunctionalLayer
183+
184+ def assert_userHasPrivilegesContext(self, obj):
185+ self.assertFalse(
186+ BugTask.userHasPrivilegesContext(obj, self.factory.makePerson()))
187+
188+ def test_distribution(self):
189+ distribution = self.factory.makeDistribution()
190+ self.assert_userHasPrivilegesContext(distribution)
191+
192+ def test_distributionsourcepackage(self):
193+ dsp = self.factory.makeDistributionSourcePackage()
194+ self.assert_userHasPrivilegesContext(dsp)
195+
196+ def test_product(self):
197+ product = self.factory.makeProduct()
198+ self.assert_userHasPrivilegesContext(product)
199+
200+ def test_productseries(self):
201+ productseries = self.factory.makeProductSeries()
202+ self.assert_userHasPrivilegesContext(productseries)
203+
204+ def test_sourcepackage(self):
205+ source = self.factory.makeSourcePackage()
206+ self.assert_userHasPrivilegesContext(source)
207
208=== modified file 'lib/lp/bugs/stories/bug-release-management/xx-bug-release-management.txt'
209--- lib/lp/bugs/stories/bug-release-management/xx-bug-release-management.txt 2011-08-08 18:14:38 +0000
210+++ lib/lp/bugs/stories/bug-release-management/xx-bug-release-management.txt 2011-11-24 00:54:26 +0000
211@@ -146,7 +146,7 @@
212 ... (dsp.name, bug_task.bug.id))
213
214 >>> admin_browser.getControl("Hydro").selected = True
215- >>> admin_browser.getControl("Nominate").click()
216+ >>> admin_browser.getControl("Target").click()
217
218 >>> for tag in find_tags_by_class(admin_browser.contents, 'message'):
219 ... print tag
220
221=== modified file 'lib/lp/registry/configure.zcml'
222--- lib/lp/registry/configure.zcml 2011-11-22 00:02:48 +0000
223+++ lib/lp/registry/configure.zcml 2011-11-24 00:54:26 +0000
224@@ -481,6 +481,7 @@
225 displayname
226 distribution
227 distro
228+ drivers
229 findRelatedArchivePublications
230 findRelatedArchives
231 getMergeProposals
232
233=== modified file 'lib/lp/registry/interfaces/distributionsourcepackage.py'
234--- lib/lp/registry/interfaces/distributionsourcepackage.py 2011-10-04 21:43:11 +0000
235+++ lib/lp/registry/interfaces/distributionsourcepackage.py 2011-11-24 00:54:26 +0000
236@@ -45,13 +45,14 @@
237 IHasMergeProposals,
238 )
239 from lp.registry.interfaces.distribution import IDistribution
240+from lp.registry.interfaces.role import IHasDrivers
241 from lp.soyuz.enums import ArchivePurpose
242
243
244 class IDistributionSourcePackage(IBugTarget, IHasBranches, IHasMergeProposals,
245 IHasOfficialBugTags,
246 IStructuralSubscriptionTarget,
247- IQuestionTarget):
248+ IQuestionTarget, IHasDrivers):
249 """Represents a source package in a distribution.
250
251 Create IDistributionSourcePackages by invoking
252@@ -122,6 +123,8 @@
253 "Number of translations matching the distribution and "
254 "sourcepackagename of the IDistributionSourcePackage.")
255
256+ drivers = Attribute("The drivers for the distribution.")
257+
258 def getReleasesAndPublishingHistory():
259 """Return a list of all releases of this source package in this
260 distribution and their corresponding publishing history.
261
262=== modified file 'lib/lp/registry/interfaces/sourcepackage.py'
263--- lib/lp/registry/interfaces/sourcepackage.py 2011-06-02 20:53:43 +0000
264+++ lib/lp/registry/interfaces/sourcepackage.py 2011-11-24 00:54:26 +0000
265@@ -58,6 +58,7 @@
266 IHasMergeProposals,
267 )
268 from lp.registry.interfaces.productseries import IProductSeries
269+from lp.registry.interfaces.role import IHasDrivers
270 from lp.soyuz.interfaces.component import IComponent
271 from lp.translations.interfaces.hastranslationtemplates import (
272 IHasTranslationTemplates,
273@@ -69,7 +70,8 @@
274
275 class ISourcePackagePublic(IBugTarget, IHasBranches, IHasMergeProposals,
276 IHasOfficialBugTags, IHasCodeImports,
277- IHasTranslationImports, IHasTranslationTemplates):
278+ IHasTranslationImports, IHasTranslationTemplates,
279+ IHasDrivers):
280 """Public attributes for SourcePackage."""
281
282 id = Attribute("ID")
283@@ -170,6 +172,9 @@
284 distribution_sourcepackage = Attribute(
285 "The IDistributionSourcePackage for this source package.")
286
287+ drivers = Attribute(
288+ "The drivers for the distroseries for this source package.")
289+
290 def __getitem__(version):
291 """Return the source package release with the given version in this
292 distro series, or None."""
293
294=== modified file 'lib/lp/registry/model/distributionsourcepackage.py'
295--- lib/lp/registry/model/distributionsourcepackage.py 2011-11-10 13:55:16 +0000
296+++ lib/lp/registry/model/distributionsourcepackage.py 2011-11-24 00:54:26 +0000
297@@ -63,6 +63,7 @@
298 )
299 from lp.registry.interfaces.pocket import PackagePublishingPocket
300 from lp.registry.model.distroseries import DistroSeries
301+from lp.registry.model.hasdrivers import HasDriversMixin
302 from lp.registry.model.karma import KarmaTotalCache
303 from lp.registry.model.packaging import Packaging
304 from lp.registry.model.sourcepackage import (
305@@ -131,7 +132,8 @@
306 HasBranchesMixin,
307 HasCustomLanguageCodesMixin,
308 HasMergeProposalsMixin,
309- HasBugHeatMixin):
310+ HasBugHeatMixin,
311+ HasDriversMixin):
312 """This is a "Magic Distribution Source Package". It is not an
313 SQLObject, but instead it represents a source package with a particular
314 name in a particular distribution. You can then ask it all sorts of
315@@ -219,6 +221,11 @@
316 return self._get(
317 self.distribution, self.sourcepackagename) is not None
318
319+ @property
320+ def drivers(self):
321+ """See `IHasDrivers`."""
322+ return self.distribution.drivers
323+
324 def delete(self):
325 """See `DistributionSourcePackage`."""
326 dsp_in_db = self._self_in_database
327
328=== modified file 'lib/lp/registry/model/sourcepackage.py'
329--- lib/lp/registry/model/sourcepackage.py 2011-09-28 03:28:50 +0000
330+++ lib/lp/registry/model/sourcepackage.py 2011-11-24 00:54:26 +0000
331@@ -528,6 +528,11 @@
332 """See `IHasBugs`."""
333 return self.distribution_sourcepackage.max_bug_heat
334
335+ @property
336+ def drivers(self):
337+ """See `IHasDrivers`."""
338+ return self.distroseries.drivers
339+
340 def createBug(self, bug_params):
341 """See canonical.launchpad.interfaces.IBugTarget."""
342 # We don't currently support opening a new bug directly on an
343
344=== modified file 'lib/lp/registry/tests/test_distributionsourcepackage.py'
345--- lib/lp/registry/tests/test_distributionsourcepackage.py 2011-11-10 20:23:30 +0000
346+++ lib/lp/registry/tests/test_distributionsourcepackage.py 2011-11-24 00:54:26 +0000
347@@ -145,6 +145,14 @@
348 dsp = self.factory.makeDistributionSourcePackage(with_db=False)
349 self.assertFalse(dsp.is_official)
350
351+ def test_drivers_are_distributions(self):
352+ # DSP.drivers returns the drivers for the distribution.
353+ distribution = self.factory.makeDistribution()
354+ dsp = self.factory.makeDistributionSourcePackage(
355+ distribution=distribution)
356+ self.assertNotEqual([], distribution.drivers)
357+ self.assertEqual(dsp.drivers, distribution.drivers)
358+
359
360 class TestDistributionSourcePackageFindRelatedArchives(TestCaseWithFactory):
361
362
363=== modified file 'lib/lp/registry/tests/test_sourcepackage.py'
364--- lib/lp/registry/tests/test_sourcepackage.py 2011-09-19 22:43:14 +0000
365+++ lib/lp/registry/tests/test_sourcepackage.py 2011-11-24 00:54:26 +0000
366@@ -494,6 +494,14 @@
367 self.assertEqual(
368 expected, sourcepackage.getSharingDetailPermissions())
369
370+ def test_drivers_are_distroseries(self):
371+ # SP.drivers returns the drivers for the distroseries.
372+ distroseries = self.factory.makeDistroSeries()
373+ sourcepackage = self.factory.makeSourcePackage(
374+ distroseries=distroseries)
375+ self.assertNotEqual([], distroseries.drivers)
376+ self.assertEqual(sourcepackage.drivers, distroseries.drivers)
377+
378
379 class TestSourcePackageWebService(WebServiceTestCase):
380