Merge lp:~wgrant/launchpad/bug-restrict-type into lp:launchpad

Proposed by William Grant
Status: Merged
Approved by: William Grant
Approved revision: no longer in the source branch.
Merged at revision: 15887
Proposed branch: lp:~wgrant/launchpad/bug-restrict-type
Merge into: lp:launchpad
Diff against target: 934 lines (+188/-282)
19 files modified
lib/lp/bugs/browser/bugalsoaffects.py (+1/-1)
lib/lp/bugs/browser/bugtask.py (+11/-21)
lib/lp/bugs/browser/tests/test_bug_views.py (+10/-3)
lib/lp/bugs/browser/tests/test_bugs.py (+1/-1)
lib/lp/bugs/browser/tests/test_bugtask.py (+14/-25)
lib/lp/bugs/doc/bug.txt (+0/-95)
lib/lp/bugs/errors.py (+0/-6)
lib/lp/bugs/mail/tests/test_commands.py (+8/-4)
lib/lp/bugs/model/bug.py (+9/-8)
lib/lp/bugs/model/bugtask.py (+9/-3)
lib/lp/bugs/model/tests/test_bug.py (+38/-7)
lib/lp/bugs/model/tests/test_bugtask.py (+42/-69)
lib/lp/bugs/stories/bug-also-affects/xx-bug-also-affects.txt (+14/-14)
lib/lp/bugs/tests/test_bugs_webservice.py (+7/-3)
lib/lp/code/errors.py (+0/-5)
lib/lp/code/model/branch.py (+3/-3)
lib/lp/code/model/tests/test_branch.py (+11/-14)
lib/lp/registry/enums.py (+4/-0)
lib/lp/registry/errors.py (+6/-0)
To merge this branch: bzr merge lp:~wgrant/launchpad/bug-restrict-type
Reviewer Review Type Date Requested Status
Steve Kowalik (community) code Approve
Review via email: mp+121989@code.launchpad.net

Commit message

Reject bug target or information type changes that would violate sharing policies.

Description of the change

This branch prevents bugs from transitioning to an information type that's illegal in their targets, or affecting a new target that disallows their information type.

I replaced the exceptions BranchCannotChangeInformationType and BugCannotBePrivate with a generic CannotChangeInformationType. transitionToInformationType checks directly that the new type is permitted, and createBug/createTask/transitionToTarget all use validate_target to confirm that the type is permitted in the new target.

I also extended the Proprietary single-pillar checks to Embargoed, as they were intended to have been from the start.

To post a comment you must log in.
Revision history for this message
Steve Kowalik (stevenk) wrote :

This looks like excellent work. I have one mis-giving:

373 - BranchCannotChangeInformationType,
374 - branch.setPrivate,
375 - True, branch.owner)
376 + CannotChangeInformationType,
377 + branch.setPrivate, True, branch.owner)

395 - BranchCannotChangeInformationType,
396 - branch.setPrivate,
397 - False, branch.owner)
398 + CannotChangeInformationType,
399 + branch.setPrivate, False, branch.owner)

Given you've added text to the branch cases that raise CannotChangeInformationType, can you flip these tests to making use of self.assertRaisesWithContent() and make certain the exception text is right.

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/lp/bugs/browser/bugalsoaffects.py'
--- lib/lp/bugs/browser/bugalsoaffects.py 2012-06-29 08:40:05 +0000
+++ lib/lp/bugs/browser/bugalsoaffects.py 2012-08-30 06:21:19 +0000
@@ -174,7 +174,7 @@
174 def validateStep(self, data):174 def validateStep(self, data):
175 if data.get('product'):175 if data.get('product'):
176 try:176 try:
177 validate_target(self.context.bug, data.get('product'))177 validate_new_target(self.context.bug, data.get('product'))
178 except IllegalTarget as e:178 except IllegalTarget as e:
179 self.setFieldError('product', e[0])179 self.setFieldError('product', e[0])
180 return180 return
181181
=== modified file 'lib/lp/bugs/browser/bugtask.py'
--- lib/lp/bugs/browser/bugtask.py 2012-08-29 06:24:05 +0000
+++ lib/lp/bugs/browser/bugtask.py 2012-08-30 06:21:19 +0000
@@ -222,7 +222,10 @@
222from lp.bugs.model.bugtasksearch import orderby_expression222from lp.bugs.model.bugtasksearch import orderby_expression
223from lp.code.interfaces.branchcollection import IAllBranches223from lp.code.interfaces.branchcollection import IAllBranches
224from lp.layers import FeedsLayer224from lp.layers import FeedsLayer
225from lp.registry.enums import InformationType225from lp.registry.enums import (
226 InformationType,
227 PROPRIETARY_INFORMATION_TYPES,
228 )
226from lp.registry.interfaces.distribution import (229from lp.registry.interfaces.distribution import (
227 IDistribution,230 IDistribution,
228 IDistributionSet,231 IDistributionSet,
@@ -699,7 +702,6 @@
699 cancel_url = canonical_url(self.context)702 cancel_url = canonical_url(self.context)
700 return cancel_url703 return cancel_url
701704
702
703 @cachedproperty705 @cachedproperty
704 def is_duplicate_active(self):706 def is_duplicate_active(self):
705 active = True707 active = True
@@ -3892,18 +3894,12 @@
3892 def canAddProjectTask(self):3894 def canAddProjectTask(self):
3893 """Can a new bug task on a project be added to this bug?3895 """Can a new bug task on a project be added to this bug?
38943896
3895 If a bug has any bug tasks already, were it to be private, it cannot3897 If a bug has any bug tasks already, were it to be Proprietary or
3896 be marked as also affecting any other project, so return False.3898 Embargoed, it cannot be marked as also affecting any other
38973899 project, so return False.
3898 Note: this check is currently only relevant if a bug is private.
3899 Eventually, even public bugs will have this restriction too. So what
3900 happens now is that this API is used by the tales to add a class
3901 called 'disallow-private' to the Also Affects Project link. A css rule
3902 is used to hide the link when body.private is True.
3903
3904 """3900 """
3905 bug = self.context3901 bug = self.context
3906 if bug.information_type != InformationType.PROPRIETARY:3902 if bug.information_type not in PROPRIETARY_INFORMATION_TYPES:
3907 return True3903 return True
3908 return len(bug.bugtasks) == 03904 return len(bug.bugtasks) == 0
39093905
@@ -3911,20 +3907,14 @@
3911 """Can a new bug task on a src pkg be added to this bug?3907 """Can a new bug task on a src pkg be added to this bug?
39123908
3913 If a bug has any existing bug tasks on a project, were it to3909 If a bug has any existing bug tasks on a project, were it to
3914 be private, then it cannot be marked as affecting a package,3910 be Proprietary or Embargoed, then it cannot be marked as
3915 so return False.3911 affecting a package, so return False.
39163912
3917 A task on a given package may still be illegal to add, but3913 A task on a given package may still be illegal to add, but
3918 this will be caught when bug.addTask() is attempted.3914 this will be caught when bug.addTask() is attempted.
3919
3920 Note: this check is currently only relevant if a bug is private.
3921 Eventually, even public bugs will have this restriction too. So what
3922 happens now is that this API is used by the tales to add a class
3923 called 'disallow-private' to the Also Affects Package link. A css rule
3924 is used to hide the link when body.private is True.
3925 """3915 """
3926 bug = self.context3916 bug = self.context
3927 if bug.information_type != InformationType.PROPRIETARY:3917 if bug.information_type not in PROPRIETARY_INFORMATION_TYPES:
3928 return True3918 return True
3929 for pillar in bug.affected_pillars:3919 for pillar in bug.affected_pillars:
3930 if IProduct.providedBy(pillar):3920 if IProduct.providedBy(pillar):
39313921
=== modified file 'lib/lp/bugs/browser/tests/test_bug_views.py'
--- lib/lp/bugs/browser/tests/test_bug_views.py 2012-08-29 06:57:53 +0000
+++ lib/lp/bugs/browser/tests/test_bug_views.py 2012-08-30 06:21:19 +0000
@@ -84,8 +84,11 @@
84 # We expect that both Also Affects links (for project and distro) are84 # We expect that both Also Affects links (for project and distro) are
85 # disallowed.85 # disallowed.
86 owner = self.factory.makePerson()86 owner = self.factory.makePerson()
87 product = self.factory.makeProduct(
88 bug_sharing_policy=BugSharingPolicy.PROPRIETARY)
87 bug = self.factory.makeBug(89 bug = self.factory.makeBug(
88 information_type=InformationType.PROPRIETARY, owner=owner)90 target=product, owner=owner,
91 information_type=InformationType.PROPRIETARY)
89 url = canonical_url(bug, rootsite="bugs")92 url = canonical_url(bug, rootsite="bugs")
90 browser = self.getUserBrowser(url, user=owner)93 browser = self.getUserBrowser(url, user=owner)
91 also_affects = find_tag_by_id(94 also_affects = find_tag_by_id(
@@ -101,10 +104,14 @@
101 # We expect that only the Also Affects Project link is disallowed.104 # We expect that only the Also Affects Project link is disallowed.
102 distro = self.factory.makeDistribution()105 distro = self.factory.makeDistribution()
103 owner = self.factory.makePerson()106 owner = self.factory.makePerson()
104 self.factory.makeAccessPolicy(pillar=distro)107 # XXX wgrant 2012-08-30 bug=1041002: Distributions don't have
108 # sharing policies yet, so it isn't possible legitimately create
109 # a Proprietary distro bug.
105 bug = self.factory.makeBug(110 bug = self.factory.makeBug(
106 target=distro,111 target=distro,
107 information_type=InformationType.PROPRIETARY, owner=owner)112 information_type=InformationType.PRIVATESECURITY, owner=owner)
113 removeSecurityProxy(bug).information_type = (
114 InformationType.PROPRIETARY)
108 url = canonical_url(bug, rootsite="bugs")115 url = canonical_url(bug, rootsite="bugs")
109 browser = self.getUserBrowser(url, user=owner)116 browser = self.getUserBrowser(url, user=owner)
110 also_affects = find_tag_by_id(117 also_affects = find_tag_by_id(
111118
=== modified file 'lib/lp/bugs/browser/tests/test_bugs.py'
--- lib/lp/bugs/browser/tests/test_bugs.py 2012-08-29 03:19:38 +0000
+++ lib/lp/bugs/browser/tests/test_bugs.py 2012-08-30 06:21:19 +0000
@@ -222,7 +222,7 @@
222222
223 def test_createBug_private_bug_private_bugs_false(self):223 def test_createBug_private_bug_private_bugs_false(self):
224 # createBug() adapts a kwarg to InformationType if one is is not None.224 # createBug() adapts a kwarg to InformationType if one is is not None.
225 project = self.factory.makeProduct(225 project = self.factory.makeLegacyProduct(
226 licenses=[License.OTHER_PROPRIETARY])226 licenses=[License.OTHER_PROPRIETARY])
227 with person_logged_in(project.owner):227 with person_logged_in(project.owner):
228 project.setPrivateBugs(False, project.owner)228 project.setPrivateBugs(False, project.owner)
229229
=== modified file 'lib/lp/bugs/browser/tests/test_bugtask.py'
--- lib/lp/bugs/browser/tests/test_bugtask.py 2012-08-28 09:36:42 +0000
+++ lib/lp/bugs/browser/tests/test_bugtask.py 2012-08-30 06:21:19 +0000
@@ -58,7 +58,10 @@
58 FeedsLayer,58 FeedsLayer,
59 setFirstLayer,59 setFirstLayer,
60 )60 )
61from lp.registry.enums import InformationType61from lp.registry.enums import (
62 BugSharingPolicy,
63 InformationType,
64 )
62from lp.registry.interfaces.person import PersonVisibility65from lp.registry.interfaces.person import PersonVisibility
63from lp.services.config import config66from lp.services.config import config
64from lp.services.database.constants import UTC_NOW67from lp.services.database.constants import UTC_NOW
@@ -1105,8 +1108,11 @@
1105 # A bug affecting a project cannot also affect another project or1108 # A bug affecting a project cannot also affect another project or
1106 # package.1109 # package.
1107 owner = self.factory.makePerson()1110 owner = self.factory.makePerson()
1111 product = self.factory.makeProduct(
1112 bug_sharing_policy=BugSharingPolicy.PROPRIETARY_OR_PUBLIC)
1108 bug = self.factory.makeBug(1113 bug = self.factory.makeBug(
1109 information_type=InformationType.PROPRIETARY, owner=owner)1114 target=product, owner=owner,
1115 information_type=InformationType.PROPRIETARY)
1110 with person_logged_in(owner):1116 with person_logged_in(owner):
1111 view = self._createView(bug)1117 view = self._createView(bug)
1112 self.assertFalse(view.canAddProjectTask())1118 self.assertFalse(view.canAddProjectTask())
@@ -1120,31 +1126,14 @@
1120 # could affect another package.1126 # could affect another package.
1121 distro = self.factory.makeDistribution()1127 distro = self.factory.makeDistribution()
1122 owner = self.factory.makePerson()1128 owner = self.factory.makePerson()
1123 self.factory.makeAccessPolicy(pillar=distro)
1124 bug = self.factory.makeBug(1129 bug = self.factory.makeBug(
1125 target=distro, owner=owner,1130 target=distro, owner=owner,
1126 information_type=InformationType.PROPRIETARY)1131 information_type=InformationType.PRIVATESECURITY)
1127 with person_logged_in(owner):1132 # XXX wgrant 2012-08-30 bug=1041002: Distributions don't have
1128 view = self._createView(bug)1133 # sharing policies yet, so it isn't possible legitimately create
1129 self.assertFalse(view.canAddProjectTask())1134 # a Proprietary distro bug.
1130 self.assertTrue(view.canAddPackageTask())1135 removeSecurityProxy(bug).information_type = (
1131 bug.transitionToInformationType(InformationType.USERDATA, owner)1136 InformationType.PROPRIETARY)
1132 self.assertTrue(view.canAddProjectTask())
1133 self.assertTrue(view.canAddPackageTask())
1134
1135 def test_sourcepkg_bug_cannot_affect_project(self):
1136 # A bug affecting a source pkg cannot also affect another project but
1137 # it could affect another package.
1138 distro = self.factory.makeDistribution()
1139 distroseries = self.factory.makeDistroSeries(distribution=distro)
1140 sp_name = self.factory.getOrMakeSourcePackageName()
1141 sp = self.factory.makeSourcePackage(
1142 sourcepackagename=sp_name, distroseries=distroseries)
1143 owner = self.factory.makePerson()
1144 self.factory.makeAccessPolicy(pillar=distro)
1145 bug = self.factory.makeBug(
1146 target=sp.distribution_sourcepackage, owner=owner,
1147 information_type=InformationType.PROPRIETARY)
1148 with person_logged_in(owner):1137 with person_logged_in(owner):
1149 view = self._createView(bug)1138 view = self._createView(bug)
1150 self.assertFalse(view.canAddProjectTask())1139 self.assertFalse(view.canAddProjectTask())
11511140
=== modified file 'lib/lp/bugs/doc/bug.txt'
--- lib/lp/bugs/doc/bug.txt 2012-08-27 23:58:18 +0000
+++ lib/lp/bugs/doc/bug.txt 2012-08-30 06:21:19 +0000
@@ -654,101 +654,6 @@
654 >>> print firefox_bug.default_bugtask.bugtargetdisplayname654 >>> print firefox_bug.default_bugtask.bugtargetdisplayname
655 Mozilla Firefox655 Mozilla Firefox
656656
657It's not always possible to add another bug task to a bug.
658Proprietary bugs are only allowed to affect a single project or distribution.
659
660 >>> params = CreateBugParams(
661 ... title="a test private bug",
662 ... comment="a description of the bug",
663 ... owner=current_user())
664 >>> private_bug = firefox.createBug(params)
665 >>> ignored = factory.makeAccessPolicy(pillar=firefox)
666 >>> private_bug.transitionToInformationType(
667 ... InformationType.PROPRIETARY, current_user())
668 True
669
670 >>> params = CreateBugParams(
671 ... title="a test public bug",
672 ... comment="a description of the bug",
673 ... owner=current_user())
674 >>> public_bug = firefox.createBug(params)
675
676We can always add any new bug task to a public bug.
677
678 >>> tomcat = getUtility(IProductSet).getByName('tomcat')
679 >>> public_bug.addTask(owner=foobar, target=tomcat)
680 <BugTask for bug...
681
682 >>> target = tomcat.getSeries('trunk')
683 >>> public_bug.addTask(owner=foobar, target=target)
684 <BugTask for bug...
685
686If we try and add an invalid bug task to a private bug we get an exception.
687
688 >>> private_bug.addTask(owner=foobar, target=tomcat)
689 Traceback (most recent call last):
690 ...
691 IllegalTarget: This proprietary bug already affects Mozilla Firefox.
692 Proprietary bugs cannot affect multiple projects.
693
694 >>> private_bug.addTask(owner=foobar, target=ubuntu)
695 Traceback (most recent call last):
696 ...
697 IllegalTarget: This proprietary bug already affects Mozilla Firefox.
698 Proprietary bugs cannot affect multiple projects.
699
700We can add a new product series task so long as it's for the same product as
701is already targeted.
702
703 >>> target = firefox.getSeries('1.0')
704 >>> private_bug.addTask(owner=foobar, target=target)
705 <BugTask for bug...
706
707 >>> target = tomcat.getSeries('trunk')
708 >>> private_bug.addTask(owner=foobar, target=target)
709 Traceback (most recent call last):
710 ...
711 IllegalTarget: This proprietary bug already affects Mozilla Firefox.
712 Proprietary bugs cannot affect multiple projects.
713
714Now we create a bug on a distribution.
715
716 >>> private_bug = ubuntu.createBug(params)
717 >>> private_bug.setPrivate(True, current_user())
718 True
719
720We can add a new distro series task so long as it's for the same distro as
721is already targeted.
722
723 >>> private_bug.addTask(owner=foobar, target=warty)
724 <BugTask for bug...
725
726We can also add an allowed distro series source package.
727
728 >>> private_bug.addTask(owner=foobar, target=warty_fox_package)
729 <BugTask for bug...
730
731We cannot add distro series or source package tasks for different distros.
732
733 >>> private_bug = tubuntu.createBug(params)
734 >>> ignored = factory.makeAccessPolicy(pillar=tubuntu)
735 >>> private_bug.transitionToInformationType(
736 ... InformationType.PROPRIETARY, current_user())
737 True
738
739 >>> private_bug.addTask(owner=foobar, target=warty)
740 Traceback (most recent call last):
741 ...
742 IllegalTarget: This proprietary bug already affects Tubuntu.
743 Proprietary bugs cannot affect multiple projects.
744
745 >>> private_bug.addTask(owner=foobar, target=warty_fox_package)
746 Traceback (most recent call last):
747 ...
748 IllegalTarget: This proprietary bug already affects Tubuntu.
749 Proprietary bugs cannot affect multiple projects.
750
751
752Changing bug visibility.657Changing bug visibility.
753658
754 >>> bug_before_modification = Snapshot(firefox_bug, providing=IBug)659 >>> bug_before_modification = Snapshot(firefox_bug, providing=IBug)
755660
=== modified file 'lib/lp/bugs/errors.py'
--- lib/lp/bugs/errors.py 2012-08-08 04:48:40 +0000
+++ lib/lp/bugs/errors.py 2012-08-30 06:21:19 +0000
@@ -5,7 +5,6 @@
55
6__metaclass__ = type6__metaclass__ = type
7__all__ = [7__all__ = [
8 'BugCannotBePrivate',
9 'InvalidDuplicateValue',8 'InvalidDuplicateValue',
10]9]
1110
@@ -19,8 +18,3 @@
19@error_status(httplib.EXPECTATION_FAILED)18@error_status(httplib.EXPECTATION_FAILED)
20class InvalidDuplicateValue(LaunchpadValidationError):19class InvalidDuplicateValue(LaunchpadValidationError):
21 """A bug cannot be set as the duplicate of another."""20 """A bug cannot be set as the duplicate of another."""
22
23
24@error_status(httplib.BAD_REQUEST)
25class BugCannotBePrivate(Exception):
26 """The bug is not allowed to be private."""
2721
=== modified file 'lib/lp/bugs/mail/tests/test_commands.py'
--- lib/lp/bugs/mail/tests/test_commands.py 2012-08-27 23:58:18 +0000
+++ lib/lp/bugs/mail/tests/test_commands.py 2012-08-30 06:21:19 +0000
@@ -20,7 +20,10 @@
20 TagEmailCommand,20 TagEmailCommand,
21 UnsubscribeEmailCommand,21 UnsubscribeEmailCommand,
22 )22 )
23from lp.registry.enums import InformationType23from lp.registry.enums import (
24 BugSharingPolicy,
25 InformationType,
26 )
24from lp.services.mail.interfaces import (27from lp.services.mail.interfaces import (
25 BugTargetNotFound,28 BugTargetNotFound,
26 EmailProcessingError,29 EmailProcessingError,
@@ -286,11 +289,12 @@
286 def test_execute_bug_cannot_add_task(self):289 def test_execute_bug_cannot_add_task(self):
287 # Test that attempts to invalidly add a new bug task results in the290 # Test that attempts to invalidly add a new bug task results in the
288 # expected error message.291 # expected error message.
289 product = self.factory.makeProduct()292 product = self.factory.makeProduct(
290 self.factory.makeAccessPolicy(pillar=product)293 bug_sharing_policy=BugSharingPolicy.PROPRIETARY)
291 bug = self.factory.makeBug(294 bug = self.factory.makeBug(
292 target=product, information_type=InformationType.PROPRIETARY)295 target=product, information_type=InformationType.PROPRIETARY)
293 self.factory.makeProduct(name='fnord')296 self.factory.makeProduct(
297 name='fnord', bug_sharing_policy=BugSharingPolicy.PROPRIETARY)
294 login_celebrity('admin')298 login_celebrity('admin')
295 login_person(bug.owner)299 login_person(bug.owner)
296 command = AffectsEmailCommand('affects', ['fnord'])300 command = AffectsEmailCommand('affects', ['fnord'])
297301
=== modified file 'lib/lp/bugs/model/bug.py'
--- lib/lp/bugs/model/bug.py 2012-08-24 05:09:51 +0000
+++ lib/lp/bugs/model/bug.py 2012-08-30 06:21:19 +0000
@@ -100,10 +100,7 @@
100 UnsubscribedFromBug,100 UnsubscribedFromBug,
101 )101 )
102from lp.bugs.enums import BugNotificationLevel102from lp.bugs.enums import BugNotificationLevel
103from lp.bugs.errors import (103from lp.bugs.errors import InvalidDuplicateValue
104 BugCannotBePrivate,
105 InvalidDuplicateValue,
106 )
107from lp.bugs.interfaces.bug import (104from lp.bugs.interfaces.bug import (
108 IBug,105 IBug,
109 IBugBecameQuestionEvent,106 IBugBecameQuestionEvent,
@@ -160,8 +157,10 @@
160from lp.registry.enums import (157from lp.registry.enums import (
161 InformationType,158 InformationType,
162 PRIVATE_INFORMATION_TYPES,159 PRIVATE_INFORMATION_TYPES,
160 PROPRIETARY_INFORMATION_TYPES,
163 SECURITY_INFORMATION_TYPES,161 SECURITY_INFORMATION_TYPES,
164 )162 )
163from lp.registry.errors import CannotChangeInformationType
165from lp.registry.interfaces.accesspolicy import (164from lp.registry.interfaces.accesspolicy import (
166 IAccessArtifactGrantSource,165 IAccessArtifactGrantSource,
167 IAccessArtifactSource,166 IAccessArtifactSource,
@@ -1710,10 +1709,12 @@
1710 """See `IBug`."""1709 """See `IBug`."""
1711 if self.information_type == information_type:1710 if self.information_type == information_type:
1712 return False1711 return False
1713 if (information_type == InformationType.PROPRIETARY and1712 if information_type not in self.getAllowedInformationTypes(who):
1714 len(self.affected_pillars) > 1):1713 raise CannotChangeInformationType("Forbidden by project policy.")
1715 raise BugCannotBePrivate(1714 if (information_type in PROPRIETARY_INFORMATION_TYPES
1716 "Multi-pillar bugs cannot be proprietary.")1715 and len(self.affected_pillars) > 1):
1716 raise CannotChangeInformationType(
1717 "Proprietary bugs can only affect one project.")
1717 if information_type in PRIVATE_INFORMATION_TYPES:1718 if information_type in PRIVATE_INFORMATION_TYPES:
1718 self.who_made_private = who1719 self.who_made_private = who
1719 self.date_made_private = UTC_NOW1720 self.date_made_private = UTC_NOW
17201721
=== modified file 'lib/lp/bugs/model/bugtask.py'
--- lib/lp/bugs/model/bugtask.py 2012-08-29 06:24:05 +0000
+++ lib/lp/bugs/model/bugtask.py 2012-08-30 06:21:19 +0000
@@ -94,7 +94,7 @@
94 )94 )
95from lp.bugs.interfaces.bugtasksearch import BugTaskSearchParams95from lp.bugs.interfaces.bugtasksearch import BugTaskSearchParams
96from lp.registry.enums import (96from lp.registry.enums import (
97 InformationType,97 PROPRIETARY_INFORMATION_TYPES,
98 PUBLIC_INFORMATION_TYPES,98 PUBLIC_INFORMATION_TYPES,
99 )99 )
100from lp.registry.interfaces.distribution import (100from lp.registry.interfaces.distribution import (
@@ -337,7 +337,13 @@
337 except NotFoundError as e:337 except NotFoundError as e:
338 raise IllegalTarget(e[0])338 raise IllegalTarget(e[0])
339339
340 if bug.information_type == InformationType.PROPRIETARY:340 legal_types = target.pillar.getAllowedBugInformationTypes()
341 if bug.information_type not in legal_types:
342 raise IllegalTarget(
343 "%s doesn't allow %s bugs." % (
344 target.pillar.bugtargetdisplayname, bug.information_type.title))
345
346 if bug.information_type in PROPRIETARY_INFORMATION_TYPES:
341 # Perhaps we are replacing the one and only existing bugtask, in347 # Perhaps we are replacing the one and only existing bugtask, in
342 # which case that's ok.348 # which case that's ok.
343 if retarget_existing and len(bug.bugtasks) <= 1:349 if retarget_existing and len(bug.bugtasks) <= 1:
@@ -348,7 +354,7 @@
348 raise IllegalTarget(354 raise IllegalTarget(
349 "This proprietary bug already affects %s. "355 "This proprietary bug already affects %s. "
350 "Proprietary bugs cannot affect multiple projects."356 "Proprietary bugs cannot affect multiple projects."
351 % bug.default_bugtask.target.bugtargetdisplayname)357 % bug.default_bugtask.target.pillar.bugtargetdisplayname)
352358
353359
354def validate_new_target(bug, target):360def validate_new_target(bug, target):
355361
=== modified file 'lib/lp/bugs/model/tests/test_bug.py'
--- lib/lp/bugs/model/tests/test_bug.py 2012-08-28 01:35:08 +0000
+++ lib/lp/bugs/model/tests/test_bug.py 2012-08-30 06:21:19 +0000
@@ -20,7 +20,6 @@
20 BugNotificationLevel,20 BugNotificationLevel,
21 BugNotificationStatus,21 BugNotificationStatus,
22 )22 )
23from lp.bugs.errors import BugCannotBePrivate
24from lp.bugs.interfaces.bugnotification import IBugNotificationSet23from lp.bugs.interfaces.bugnotification import IBugNotificationSet
25from lp.bugs.interfaces.bugtask import BugTaskStatus24from lp.bugs.interfaces.bugtask import BugTaskStatus
26from lp.bugs.mail.bugnotificationrecipients import BugNotificationRecipients25from lp.bugs.mail.bugnotificationrecipients import BugNotificationRecipients
@@ -28,7 +27,11 @@
28 BugNotification,27 BugNotification,
29 BugSubscriptionInfo,28 BugSubscriptionInfo,
30 )29 )
31from lp.registry.enums import InformationType30from lp.registry.enums import (
31 BugSharingPolicy,
32 InformationType,
33 )
34from lp.registry.errors import CannotChangeInformationType
32from lp.registry.interfaces.accesspolicy import (35from lp.registry.interfaces.accesspolicy import (
33 IAccessArtifactSource,36 IAccessArtifactSource,
34 IAccessPolicyArtifactSource,37 IAccessPolicyArtifactSource,
@@ -753,12 +756,17 @@
753756
754 def test_multipillar_proprietary_bugs_disallowed(self):757 def test_multipillar_proprietary_bugs_disallowed(self):
755 # A multi-pillar bug cannot be made proprietary.758 # A multi-pillar bug cannot be made proprietary.
756 bug = self.factory.makeBug()759 p1 = self.factory.makeProduct(
757 product = self.factory.makeProduct()760 bug_sharing_policy=BugSharingPolicy.PUBLIC_OR_PROPRIETARY)
758 self.factory.makeBugTask(bug=bug, target=product)761 p2 = self.factory.makeProduct(
762 bug_sharing_policy=BugSharingPolicy.PUBLIC_OR_PROPRIETARY)
763 bug = self.factory.makeBug(target=p1)
764 self.factory.makeBugTask(bug=bug, target=p2)
759 login_person(bug.owner)765 login_person(bug.owner)
760 self.assertRaises(766 self.assertRaisesWithContent(
761 BugCannotBePrivate, bug.transitionToInformationType,767 CannotChangeInformationType,
768 "Proprietary bugs can only affect one project.",
769 bug.transitionToInformationType,
762 InformationType.PROPRIETARY, bug.owner)770 InformationType.PROPRIETARY, bug.owner)
763 bug.transitionToInformationType(InformationType.USERDATA, bug.owner)771 bug.transitionToInformationType(InformationType.USERDATA, bug.owner)
764 self.assertTrue(bug.private)772 self.assertTrue(bug.private)
@@ -869,6 +877,29 @@
869 InformationType.PRIVATESECURITY, InformationType.USERDATA],877 InformationType.PRIVATESECURITY, InformationType.USERDATA],
870 self.factory.makeBug().getAllowedInformationTypes(None))878 self.factory.makeBug().getAllowedInformationTypes(None))
871879
880 def test_transitionToInformationType_respects_allowed_proprietary(self):
881 # transitionToInformationType rejects types that aren't allowed
882 # for the bug.
883 product = self.factory.makeProduct()
884 with person_logged_in(product.owner):
885 bug = self.factory.makeBug(target=product)
886 self.assertRaisesWithContent(
887 CannotChangeInformationType, "Forbidden by project policy.",
888 bug.transitionToInformationType,
889 InformationType.PROPRIETARY, bug.owner)
890
891 def test_transitionToInformationType_respects_allowed_public(self):
892 # transitionToInformationType rejects types that aren't allowed
893 # for the bug.
894 product = self.factory.makeProduct(
895 bug_sharing_policy=BugSharingPolicy.PROPRIETARY)
896 with person_logged_in(product.owner):
897 bug = self.factory.makeBug(target=product)
898 self.assertRaisesWithContent(
899 CannotChangeInformationType, "Forbidden by project policy.",
900 bug.transitionToInformationType,
901 InformationType.PUBLIC, bug.owner)
902
872903
873class TestBugPrivateAndSecurityRelatedUpdatesPrivateProject(904class TestBugPrivateAndSecurityRelatedUpdatesPrivateProject(
874 TestBugPrivateAndSecurityRelatedUpdatesMixin, TestCaseWithFactory):905 TestBugPrivateAndSecurityRelatedUpdatesMixin, TestCaseWithFactory):
875906
=== modified file 'lib/lp/bugs/model/tests/test_bugtask.py'
--- lib/lp/bugs/model/tests/test_bugtask.py 2012-08-29 06:24:05 +0000
+++ lib/lp/bugs/model/tests/test_bugtask.py 2012-08-30 06:21:19 +0000
@@ -56,6 +56,7 @@
56 )56 )
57from lp.bugs.tests.bug import create_old_bug57from lp.bugs.tests.bug import create_old_bug
58from lp.registry.enums import (58from lp.registry.enums import (
59 BugSharingPolicy,
59 InformationType,60 InformationType,
60 TeamMembershipPolicy,61 TeamMembershipPolicy,
61 )62 )
@@ -2847,52 +2848,26 @@
2847 a private bugs to check for multi-tenant constraints.2848 a private bugs to check for multi-tenant constraints.
2848 """2849 """
28492850
2850 def test_private_multi_tenanted_forbidden(self):
2851 # A new task project cannot be added if there is already one from
2852 # another pillar.
2853 d = self.factory.makeDistribution()
2854 bug = self.factory.makeBug(target=d)
2855 if not self.multi_tenant_test_one_task_only:
2856 self.factory.makeBugTask(bug=bug)
2857 p = self.factory.makeProduct()
2858 self.factory.makeAccessPolicy(pillar=d)
2859 with person_logged_in(bug.owner):
2860 bug.transitionToInformationType(
2861 InformationType.PROPRIETARY, bug.owner)
2862 self.assertRaisesWithContent(
2863 IllegalTarget,
2864 "This proprietary bug already affects %s. "
2865 "Proprietary bugs cannot affect multiple projects."
2866 % d.displayname,
2867 self.validate_method, bug, p)
2868 bug.transitionToInformationType(
2869 InformationType.USERDATA, bug.owner)
2870 self.validate_method(bug, p)
2871
2872 def test_private_incorrect_pillar_task_forbidden(self):2851 def test_private_incorrect_pillar_task_forbidden(self):
2873 # A product or distro cannot be added if there is already a bugtask.2852 # Another pillar cannot be added if there is already a bugtask.
2874 p1 = self.factory.makeProduct()2853 p1 = self.factory.makeProduct(
2875 p2 = self.factory.makeProduct()2854 bug_sharing_policy=BugSharingPolicy.PROPRIETARY_OR_PUBLIC)
2876 d = self.factory.makeDistribution()2855 p2 = self.factory.makeProduct(
2877 bug = self.factory.makeBug(target=p1)2856 bug_sharing_policy=BugSharingPolicy.PROPRIETARY_OR_PUBLIC)
2857 owner = self.factory.makePerson()
2858 bug = self.factory.makeBug(target=p1, owner=owner)
2859 # validate_target allows cross-pillar transitions if there's
2860 # only one task, so we might need to create a second task to test.
2878 if not self.multi_tenant_test_one_task_only:2861 if not self.multi_tenant_test_one_task_only:
2879 self.factory.makeBugTask(bug=bug)2862 self.factory.makeBugTask(
2880 self.factory.makeAccessPolicy(pillar=p1)2863 bug=bug, target=self.factory.makeProductSeries(product=p1))
2881 with person_logged_in(bug.owner):2864 with person_logged_in(owner):
2882 bug.transitionToInformationType(
2883 InformationType.PROPRIETARY, bug.owner)
2884 self.assertRaisesWithContent(2865 self.assertRaisesWithContent(
2885 IllegalTarget,2866 IllegalTarget,
2886 "This proprietary bug already affects %s. "2867 "This proprietary bug already affects %s. "
2887 "Proprietary bugs cannot affect multiple projects."2868 "Proprietary bugs cannot affect multiple projects."
2888 % p1.displayname,2869 % p1.displayname,
2889 self.validate_method, bug, p2)2870 self.validate_method, bug, p2)
2890 self.assertRaisesWithContent(
2891 IllegalTarget,
2892 "This proprietary bug already affects %s. "
2893 "Proprietary bugs cannot affect multiple projects."
2894 % p1.displayname,
2895 self.validate_method, bug, d)
2896 bug.transitionToInformationType(2871 bug.transitionToInformationType(
2897 InformationType.USERDATA, bug.owner)2872 InformationType.USERDATA, bug.owner)
2898 self.validate_method(bug, p2)2873 self.validate_method(bug, p2)
@@ -2900,16 +2875,19 @@
2900 def test_private_incorrect_product_series_task_forbidden(self):2875 def test_private_incorrect_product_series_task_forbidden(self):
2901 # A product series cannot be added if there is already a bugtask for2876 # A product series cannot be added if there is already a bugtask for
2902 # a different product.2877 # a different product.
2903 p1 = self.factory.makeProduct()2878 p1 = self.factory.makeProduct(
2904 p2 = self.factory.makeProduct()2879 bug_sharing_policy=BugSharingPolicy.PROPRIETARY_OR_PUBLIC)
2880 p2 = self.factory.makeProduct(
2881 bug_sharing_policy=BugSharingPolicy.PROPRIETARY_OR_PUBLIC)
2905 series = self.factory.makeProductSeries(product=p2)2882 series = self.factory.makeProductSeries(product=p2)
2906 bug = self.factory.makeBug(target=p1)2883 owner = self.factory.makePerson()
2884 bug = self.factory.makeBug(target=p1, owner=owner)
2885 # validate_target allows cross-pillar transitions if there's
2886 # only one task, so we might need to create a second task to test.
2907 if not self.multi_tenant_test_one_task_only:2887 if not self.multi_tenant_test_one_task_only:
2908 self.factory.makeBugTask(bug=bug)2888 self.factory.makeBugTask(
2909 self.factory.makeAccessPolicy(pillar=p1)2889 bug=bug, target=self.factory.makeProductSeries(product=p1))
2910 with person_logged_in(bug.owner):2890 with person_logged_in(owner):
2911 bug.transitionToInformationType(
2912 InformationType.PROPRIETARY, bug.owner)
2913 self.assertRaisesWithContent(2891 self.assertRaisesWithContent(
2914 IllegalTarget,2892 IllegalTarget,
2915 "This proprietary bug already affects %s. "2893 "This proprietary bug already affects %s. "
@@ -2920,29 +2898,6 @@
2920 InformationType.USERDATA, bug.owner)2898 InformationType.USERDATA, bug.owner)
2921 self.validate_method(bug, series)2899 self.validate_method(bug, series)
29222900
2923 def test_private_incorrect_distro_series_task_forbidden(self):
2924 # A distro series cannot be added if there is already a bugtask for
2925 # a different distro.
2926 d1 = self.factory.makeDistribution()
2927 d2 = self.factory.makeDistribution()
2928 series = self.factory.makeDistroSeries(distribution=d2)
2929 bug = self.factory.makeBug(target=d1)
2930 if not self.multi_tenant_test_one_task_only:
2931 self.factory.makeBugTask(bug=bug)
2932 self.factory.makeAccessPolicy(pillar=d1)
2933 with person_logged_in(bug.owner):
2934 bug.transitionToInformationType(
2935 InformationType.PROPRIETARY, bug.owner)
2936 self.assertRaisesWithContent(
2937 IllegalTarget,
2938 "This proprietary bug already affects %s. "
2939 "Proprietary bugs cannot affect multiple projects."
2940 % d1.displayname,
2941 self.validate_method, bug, series)
2942 bug.transitionToInformationType(
2943 InformationType.USERDATA, bug.owner)
2944 self.validate_method(bug, series)
2945
29462901
2947class TestValidateTarget(TestCaseWithFactory, ValidateTargetMixin):2902class TestValidateTarget(TestCaseWithFactory, ValidateTargetMixin):
29482903
@@ -3082,6 +3037,24 @@
3082 % (dsp.sourcepackagename.name, dsp.distribution.displayname),3037 % (dsp.sourcepackagename.name, dsp.distribution.displayname),
3083 validate_target, task.bug, dsp)3038 validate_target, task.bug, dsp)
30843039
3040 def test_illegal_information_type_disallowed(self):
3041 # The bug's current information_type must be permitted by the
3042 # new target.
3043 free_prod = self.factory.makeProduct()
3044 other_free_prod = self.factory.makeProduct()
3045 commercial_prod = self.factory.makeProduct(
3046 bug_sharing_policy=BugSharingPolicy.PROPRIETARY)
3047 bug = self.factory.makeBug(target=free_prod)
3048
3049 # The new bug is Public, which is legal on the other free product.
3050 self.assertIs(None, validate_target(bug, other_free_prod))
3051
3052 # But not on the proprietary-only product.
3053 self.assertRaisesWithContent(
3054 IllegalTarget,
3055 "%s doesn't allow Public bugs." % commercial_prod.displayname,
3056 validate_target, bug, commercial_prod)
3057
30853058
3086class TestValidateNewTarget(TestCaseWithFactory, ValidateTargetMixin):3059class TestValidateNewTarget(TestCaseWithFactory, ValidateTargetMixin):
30873060
30883061
=== modified file 'lib/lp/bugs/stories/bug-also-affects/xx-bug-also-affects.txt'
--- lib/lp/bugs/stories/bug-also-affects/xx-bug-also-affects.txt 2012-08-27 23:58:18 +0000
+++ lib/lp/bugs/stories/bug-also-affects/xx-bug-also-affects.txt 2012-08-30 06:21:19 +0000
@@ -201,41 +201,41 @@
201 ...>pmount (Debian)</a>...201 ...>pmount (Debian)</a>...
202 ...202 ...
203203
204We cannot allow private bugs to affect more than one pillar.204We cannot allow proprietary bugs to affect more than one pillar.
205205
206 >>> from lp.services.webapp import canonical_url206 >>> from lp.services.webapp import canonical_url
207 >>> from lp.services.webapp.interfaces import ILaunchBag207 >>> from lp.services.webapp.interfaces import ILaunchBag
208 >>> from lp.bugs.interfaces.bug import CreateBugParams208 >>> from lp.bugs.interfaces.bug import CreateBugParams
209 >>> from lp.registry.interfaces.product import IProductSet209 >>> from lp.registry.enums import BugSharingPolicy, InformationType
210 >>> from lp.registry.enums import InformationType
211210
212 >>> def current_user():211 >>> def current_user():
213 ... return getUtility(ILaunchBag).user212 ... return getUtility(ILaunchBag).user
214213
215 >>> login("foo.bar@canonical.com")214 >>> login("test@canonical.com")
216 >>> productset = getUtility(IProductSet)215 >>> product = factory.makeProduct(
217 >>> firefox = productset.get(4)216 ... displayname='Proprietary Product', name='proprietary-product',
218 >>> ignored = factory.makeAccessPolicy(pillar=firefox)217 ... bug_sharing_policy=BugSharingPolicy.PROPRIETARY)
218 >>> other_product = factory.makeProduct(
219 ... official_malone=True,
220 ... bug_sharing_policy=BugSharingPolicy.PROPRIETARY)
219 >>> params = CreateBugParams(221 >>> params = CreateBugParams(
220 ... title="a test private bug",222 ... title="a test private bug",
221 ... comment="a description of the bug",223 ... comment="a description of the bug",
222 ... information_type=InformationType.PROPRIETARY,224 ... information_type=InformationType.PROPRIETARY,
223 ... owner=current_user())225 ... owner=current_user())
224 >>> private_bug = firefox.createBug(params)226 >>> private_bug = product.createBug(params)
225 >>> private_bug.subscribe(firefox.owner, firefox.owner)
226 <lp.bugs.model.bugsubscription.BugSubscription object at ...>
227 >>> logout()227 >>> logout()
228228
229 >>> browser.open(canonical_url(private_bug, rootsite='bugs'))229 >>> browser.open(canonical_url(private_bug, rootsite='bugs'))
230 >>> browser.getLink(url='+distrotask').click()230 >>> browser.getLink(url='+choose-affected-product').click()
231 >>> browser.getControl(name='field.distribution').value = ['debian']231 >>> browser.getControl(name='field.product').value = other_product.name
232 >>> browser.getControl('Continue').click()232 >>> browser.getControl('Continue').click()
233 >>> print browser.url233 >>> print browser.url
234 http://bugs.launchpad.dev/firefox/+bug/16/+distrotask234 http://bugs.launchpad.dev/proprietary-product/+bug/16/+choose-affected-product
235235
236 >>> print get_feedback_messages(browser.contents)236 >>> print get_feedback_messages(browser.contents)
237 [u'There is 1 error.',237 [u'There is 1 error.',
238 u'This proprietary bug already affects Mozilla Firefox.238 u'This proprietary bug already affects Proprietary Product.
239 Proprietary bugs cannot affect multiple projects.']239 Proprietary bugs cannot affect multiple projects.']
240240
241241
242242
=== modified file 'lib/lp/bugs/tests/test_bugs_webservice.py'
--- lib/lp/bugs/tests/test_bugs_webservice.py 2012-08-29 06:57:53 +0000
+++ lib/lp/bugs/tests/test_bugs_webservice.py 2012-08-30 06:21:19 +0000
@@ -361,15 +361,19 @@
361 # a proprietary bug. In this case, we cannot mark a proprietary bug361 # a proprietary bug. In this case, we cannot mark a proprietary bug
362 # as affecting more than one project.362 # as affecting more than one project.
363 owner = self.factory.makePerson()363 owner = self.factory.makePerson()
364 product1 = self.factory.makeProduct(
365 bug_sharing_policy=BugSharingPolicy.PROPRIETARY)
366 product2 = self.factory.makeProduct(
367 bug_sharing_policy=BugSharingPolicy.PROPRIETARY)
364 bug = self.factory.makeBug(368 bug = self.factory.makeBug(
365 owner=owner, information_type=InformationType.PROPRIETARY)369 target=product1, owner=owner,
366 product = self.factory.makeProduct()370 information_type=InformationType.PROPRIETARY)
367371
368 login_person(owner)372 login_person(owner)
369 launchpad = launchpadlib_for('test', owner)373 launchpad = launchpadlib_for('test', owner)
370 lp_bug = launchpad.load(api_url(bug))374 lp_bug = launchpad.load(api_url(bug))
371 self.assertRaises(375 self.assertRaises(
372 BadRequest, lp_bug.addTask, target=api_url(product))376 BadRequest, lp_bug.addTask, target=api_url(product2))
373377
374378
375class BugSetTestCase(TestCaseWithFactory):379class BugSetTestCase(TestCaseWithFactory):
376380
=== modified file 'lib/lp/code/errors.py'
--- lib/lp/code/errors.py 2012-07-11 09:36:13 +0000
+++ lib/lp/code/errors.py 2012-08-30 06:21:19 +0000
@@ -8,7 +8,6 @@
8 'AlreadyLatestFormat',8 'AlreadyLatestFormat',
9 'BadBranchMergeProposalSearchContext',9 'BadBranchMergeProposalSearchContext',
10 'BadStateTransition',10 'BadStateTransition',
11 'BranchCannotChangeInformationType',
12 'BranchCreationException',11 'BranchCreationException',
13 'BranchCreationForbidden',12 'BranchCreationForbidden',
14 'BranchCreatorNotMemberOfOwnerTeam',13 'BranchCreatorNotMemberOfOwnerTeam',
@@ -146,10 +145,6 @@
146 """145 """
147146
148147
149class BranchCannotChangeInformationType(Exception):
150 """The information type of this branch cannot be changed."""
151
152
153class InvalidBranchException(Exception):148class InvalidBranchException(Exception):
154 """Base exception for an error resolving a branch for a component.149 """Base exception for an error resolving a branch for a component.
155150
156151
=== modified file 'lib/lp/code/model/branch.py'
--- lib/lp/code/model/branch.py 2012-08-29 02:40:36 +0000
+++ lib/lp/code/model/branch.py 2012-08-30 06:21:19 +0000
@@ -80,7 +80,6 @@
80 )80 )
81from lp.code.errors import (81from lp.code.errors import (
82 AlreadyLatestFormat,82 AlreadyLatestFormat,
83 BranchCannotChangeInformationType,
84 BranchMergeProposalExists,83 BranchMergeProposalExists,
85 BranchTargetError,84 BranchTargetError,
86 BranchTypeError,85 BranchTypeError,
@@ -137,6 +136,7 @@
137 PRIVATE_INFORMATION_TYPES,136 PRIVATE_INFORMATION_TYPES,
138 PUBLIC_INFORMATION_TYPES,137 PUBLIC_INFORMATION_TYPES,
139 )138 )
139from lp.registry.errors import CannotChangeInformationType
140from lp.registry.interfaces.accesspolicy import (140from lp.registry.interfaces.accesspolicy import (
141 IAccessArtifactGrantSource,141 IAccessArtifactGrantSource,
142 IAccessArtifactSource,142 IAccessArtifactSource,
@@ -249,10 +249,10 @@
249 if (self.stacked_on249 if (self.stacked_on
250 and self.stacked_on.information_type in PRIVATE_INFORMATION_TYPES250 and self.stacked_on.information_type in PRIVATE_INFORMATION_TYPES
251 and information_type in PUBLIC_INFORMATION_TYPES):251 and information_type in PUBLIC_INFORMATION_TYPES):
252 raise BranchCannotChangeInformationType()252 raise CannotChangeInformationType("Must match stacked-on branch.")
253 if (verify_policy253 if (verify_policy
254 and information_type not in self.getAllowedInformationTypes(who)):254 and information_type not in self.getAllowedInformationTypes(who)):
255 raise BranchCannotChangeInformationType()255 raise CannotChangeInformationType("Forbidden by project policy.")
256 self.information_type = information_type256 self.information_type = information_type
257 self._reconcileAccess()257 self._reconcileAccess()
258 if information_type in PRIVATE_INFORMATION_TYPES and self.subscribers:258 if information_type in PRIVATE_INFORMATION_TYPES and self.subscribers:
259259
=== modified file 'lib/lp/code/model/tests/test_branch.py'
--- lib/lp/code/model/tests/test_branch.py 2012-08-29 03:19:38 +0000
+++ lib/lp/code/model/tests/test_branch.py 2012-08-30 06:21:19 +0000
@@ -54,7 +54,6 @@
54 )54 )
55from lp.code.errors import (55from lp.code.errors import (
56 AlreadyLatestFormat,56 AlreadyLatestFormat,
57 BranchCannotChangeInformationType,
58 BranchCreatorNotMemberOfOwnerTeam,57 BranchCreatorNotMemberOfOwnerTeam,
59 BranchCreatorNotOwner,58 BranchCreatorNotOwner,
60 BranchTargetError,59 BranchTargetError,
@@ -120,6 +119,7 @@
120 PUBLIC_INFORMATION_TYPES,119 PUBLIC_INFORMATION_TYPES,
121 TeamMembershipPolicy,120 TeamMembershipPolicy,
122 )121 )
122from lp.registry.errors import CannotChangeInformationType
123from lp.registry.interfaces.accesspolicy import (123from lp.registry.interfaces.accesspolicy import (
124 IAccessArtifactSource,124 IAccessArtifactSource,
125 IAccessPolicyArtifactSource,125 IAccessPolicyArtifactSource,
@@ -2480,13 +2480,12 @@
24802480
2481 def test_public_to_private_not_allowed(self):2481 def test_public_to_private_not_allowed(self):
2482 # If there are no privacy policies allowing private branches, then2482 # If there are no privacy policies allowing private branches, then
2483 # BranchCannotChangeInformationType is rasied.2483 # CannotChangeInformationType is raised.
2484 product = self.factory.makeLegacyProduct()2484 product = self.factory.makeLegacyProduct()
2485 branch = self.factory.makeBranch(product=product)2485 branch = self.factory.makeBranch(product=product)
2486 self.assertRaises(2486 self.assertRaisesWithContent(
2487 BranchCannotChangeInformationType,2487 CannotChangeInformationType, 'Forbidden by project policy.',
2488 branch.setPrivate,2488 branch.setPrivate, True, branch.owner)
2489 True, branch.owner)
24902489
2491 def test_public_to_private_for_admins(self):2490 def test_public_to_private_for_admins(self):
2492 # Admins can override the default behaviour and make any public branch2491 # Admins can override the default behaviour and make any public branch
@@ -2522,8 +2521,7 @@
25222521
2523 def test_private_to_public_not_allowed(self):2522 def test_private_to_public_not_allowed(self):
2524 # If the namespace policy does not allow public branches, attempting2523 # If the namespace policy does not allow public branches, attempting
2525 # to change the branch to be public raises2524 # to change the branch to be public raises CannotChangeInformationType.
2526 # BranchCannotChangeInformationType.
2527 product = self.factory.makeLegacyProduct()2525 product = self.factory.makeLegacyProduct()
2528 branch = self.factory.makeBranch(2526 branch = self.factory.makeBranch(
2529 product=product,2527 product=product,
@@ -2532,10 +2530,9 @@
2532 None, BranchVisibilityRule.FORBIDDEN)2530 None, BranchVisibilityRule.FORBIDDEN)
2533 branch.product.setBranchVisibilityTeamPolicy(2531 branch.product.setBranchVisibilityTeamPolicy(
2534 branch.owner, BranchVisibilityRule.PRIVATE_ONLY)2532 branch.owner, BranchVisibilityRule.PRIVATE_ONLY)
2535 self.assertRaises(2533 self.assertRaisesWithContent(
2536 BranchCannotChangeInformationType,2534 CannotChangeInformationType, 'Forbidden by project policy.',
2537 branch.setPrivate,2535 branch.setPrivate, False, branch.owner)
2538 False, branch.owner)
25392536
2540 def test_cannot_transition_with_private_stacked_on(self):2537 def test_cannot_transition_with_private_stacked_on(self):
2541 # If a public branch is stacked on a private branch, it can not2538 # If a public branch is stacked on a private branch, it can not
@@ -2543,8 +2540,8 @@
2543 stacked_on = self.factory.makeBranch(2540 stacked_on = self.factory.makeBranch(
2544 information_type=InformationType.USERDATA)2541 information_type=InformationType.USERDATA)
2545 branch = self.factory.makeBranch(stacked_on=stacked_on)2542 branch = self.factory.makeBranch(stacked_on=stacked_on)
2546 self.assertRaises(2543 self.assertRaisesWithContent(
2547 BranchCannotChangeInformationType,2544 CannotChangeInformationType, 'Must match stacked-on branch.',
2548 branch.transitionToInformationType, InformationType.PUBLIC,2545 branch.transitionToInformationType, InformationType.PUBLIC,
2549 branch.owner)2546 branch.owner)
25502547
25512548
=== modified file 'lib/lp/registry/enums.py'
--- lib/lp/registry/enums.py 2012-08-20 13:26:21 +0000
+++ lib/lp/registry/enums.py 2012-08-30 06:21:19 +0000
@@ -18,6 +18,7 @@
18 'PersonTransferJobType',18 'PersonTransferJobType',
19 'PersonVisibility',19 'PersonVisibility',
20 'PRIVATE_INFORMATION_TYPES',20 'PRIVATE_INFORMATION_TYPES',
21 'PROPRIETARY_INFORMATION_TYPES',
21 'PUBLIC_INFORMATION_TYPES',22 'PUBLIC_INFORMATION_TYPES',
22 'ProductJobType',23 'ProductJobType',
23 'SECURITY_INFORMATION_TYPES',24 'SECURITY_INFORMATION_TYPES',
@@ -97,6 +98,9 @@
97FREE_INFORMATION_TYPES = (98FREE_INFORMATION_TYPES = (
98 PUBLIC_INFORMATION_TYPES + FREE_PRIVATE_INFORMATION_TYPES)99 PUBLIC_INFORMATION_TYPES + FREE_PRIVATE_INFORMATION_TYPES)
99100
101PROPRIETARY_INFORMATION_TYPES = (
102 InformationType.PROPRIETARY, InformationType.EMBARGOED)
103
100104
101class SharingPermission(DBEnumeratedType):105class SharingPermission(DBEnumeratedType):
102 """Sharing permission.106 """Sharing permission.
103107
=== modified file 'lib/lp/registry/errors.py'
--- lib/lp/registry/errors.py 2012-08-13 20:17:56 +0000
+++ lib/lp/registry/errors.py 2012-08-30 06:21:19 +0000
@@ -5,6 +5,7 @@
5__all__ = [5__all__ = [
6 'DistroSeriesDifferenceError',6 'DistroSeriesDifferenceError',
7 'NotADerivedSeriesError',7 'NotADerivedSeriesError',
8 'CannotChangeInformationType',
8 'CannotDeleteCommercialSubscription',9 'CannotDeleteCommercialSubscription',
9 'CannotTransitionToCountryMirror',10 'CannotTransitionToCountryMirror',
10 'CommercialSubscribersOnly',11 'CommercialSubscribersOnly',
@@ -190,3 +191,8 @@
190191
191class CannotDeleteCommercialSubscription(Exception):192class CannotDeleteCommercialSubscription(Exception):
192 """Raised when a commercial subscription cannot be deleted."""193 """Raised when a commercial subscription cannot be deleted."""
194
195
196@error_status(httplib.BAD_REQUEST)
197class CannotChangeInformationType(Exception):
198 """The information type cannot be changed."""