Merge lp:~wgrant/launchpad/branchnamespace-information-type into lp:launchpad

Proposed by William Grant
Status: Merged
Approved by: Curtis Hovey
Approved revision: no longer in the source branch.
Merged at revision: 15610
Proposed branch: lp:~wgrant/launchpad/branchnamespace-information-type
Merge into: lp:launchpad
Diff against target: 696 lines (+137/-287)
6 files modified
lib/lp/code/errors.py (+0/-10)
lib/lp/code/interfaces/branchnamespace.py (+6/-16)
lib/lp/code/model/branch.py (+6/-9)
lib/lp/code/model/branchnamespace.py (+52/-76)
lib/lp/code/model/tests/test_branch.py (+5/-6)
lib/lp/code/model/tests/test_branchnamespace.py (+68/-170)
To merge this branch: bzr merge lp:~wgrant/launchpad/branchnamespace-information-type
Reviewer Review Type Date Requested Status
Curtis Hovey (community) code Approve
Review via email: mp+114387@code.launchpad.net

Commit message

Start porting IBranchNamespace's privacy methods to information types.

Description of the change

This branch prepares IBranchNamespace for the BranchVisibilityPolicy replacement. Branch privacy is no longer a binary thing; we want to be able to enable different sets of information types depending on new project configuration.

This does not yet change any behaviour. The namespace implementations still allow combinations of PUBLIC_INFORMATION_TYPES and PRIVATE_INFORMATION_TYPES, and ProductNamespace still uses BranchVisibilityPolicy. But it's the majority of the work toward an interface that can operate on both BVP and the new config system.

Some callsites are only minimally shimmed around the new getAllowedInformationTypes method. A more complete port will come in a subsequent branch.

To post a comment you must log in.
Revision history for this message
Curtis Hovey (sinzui) wrote :

Thank you.

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/code/errors.py'
2--- lib/lp/code/errors.py 2012-05-24 02:16:59 +0000
3+++ lib/lp/code/errors.py 2012-07-11 12:28:19 +0000
4@@ -8,8 +8,6 @@
5 'AlreadyLatestFormat',
6 'BadBranchMergeProposalSearchContext',
7 'BadStateTransition',
8- 'BranchCannotBePrivate',
9- 'BranchCannotBePublic',
10 'BranchCannotChangeInformationType',
11 'BranchCreationException',
12 'BranchCreationForbidden',
13@@ -148,14 +146,6 @@
14 """
15
16
17-class BranchCannotBePublic(Exception):
18- """The branch cannot be made public."""
19-
20-
21-class BranchCannotBePrivate(Exception):
22- """The branch cannot be made private."""
23-
24-
25 class BranchCannotChangeInformationType(Exception):
26 """The information type of this branch cannot be changed."""
27
28
29=== modified file 'lib/lp/code/interfaces/branchnamespace.py'
30--- lib/lp/code/interfaces/branchnamespace.py 2011-03-03 01:13:47 +0000
31+++ lib/lp/code/interfaces/branchnamespace.py 2012-07-11 12:28:19 +0000
32@@ -110,6 +110,12 @@
33 :return: A Boolean value.
34 """
35
36+ def getAllowedInformationTypes():
37+ """Get the information types that a branch in this namespace can have.
38+
39+ :return: A sequence of `InformationType`s.
40+ """
41+
42 def areNewBranchesPrivate():
43 """Are new branches in this namespace private?
44
45@@ -118,22 +124,6 @@
46 :return: A Boolean value.
47 """
48
49- def canBranchesBePrivate():
50- """Can branches by the user be private in this namespace?
51-
52- No check is made about whether or not a user can create branches.
53-
54- :return: A Boolean value.
55- """
56-
57- def canBranchesBePublic():
58- """Can branches by the user be public in this namespace?
59-
60- No check is made about whether or not a user can create branches.
61-
62- :return: A Boolean value.
63- """
64-
65 def validateRegistrant(registrant):
66 """Check that the registrant can create a branch on this namespace.
67
68
69=== modified file 'lib/lp/code/model/branch.py'
70--- lib/lp/code/model/branch.py 2012-07-10 09:51:13 +0000
71+++ lib/lp/code/model/branch.py 2012-07-11 12:28:19 +0000
72@@ -83,8 +83,6 @@
73 )
74 from lp.code.errors import (
75 AlreadyLatestFormat,
76- BranchCannotBePrivate,
77- BranchCannotBePublic,
78 BranchCannotChangeInformationType,
79 BranchMergeProposalExists,
80 BranchTargetError,
81@@ -248,14 +246,11 @@
82 and self.stacked_on.information_type in PRIVATE_INFORMATION_TYPES
83 and information_type in PUBLIC_INFORMATION_TYPES):
84 raise BranchCannotChangeInformationType()
85- private = information_type in PRIVATE_INFORMATION_TYPES
86 # Only check the privacy policy if the user is not special.
87 if verify_policy and not user_has_special_branch_access(who):
88 policy = IBranchNamespacePolicy(self.namespace)
89- if private and not policy.canBranchesBePrivate():
90- raise BranchCannotBePrivate()
91- if not private and not policy.canBranchesBePublic():
92- raise BranchCannotBePublic()
93+ if information_type not in policy.getAllowedInformationTypes():
94+ raise BranchCannotChangeInformationType()
95 self.information_type = information_type
96 self._reconcileAccess()
97 if information_type in PRIVATE_INFORMATION_TYPES:
98@@ -1300,13 +1295,15 @@
99 def canBePublic(self, user):
100 """See `IBranch`."""
101 policy = IBranchNamespacePolicy(self.namespace)
102- return policy.canBranchesBePublic()
103+ return InformationType.PUBLIC in policy.getAllowedInformationTypes()
104
105 def canBePrivate(self, user):
106 """See `IBranch`."""
107 policy = IBranchNamespacePolicy(self.namespace)
108 # Do the easy checks first.
109- if (policy.canBranchesBePrivate() or
110+ policy_allows = (
111+ InformationType.USERDATA in policy.getAllowedInformationTypes())
112+ if (policy_allows or
113 user_has_special_branch_access(user) or
114 user.visibility == PersonVisibility.PRIVATE):
115 return True
116
117=== modified file 'lib/lp/code/model/branchnamespace.py'
118--- lib/lp/code/model/branchnamespace.py 2012-06-14 09:09:59 +0000
119+++ lib/lp/code/model/branchnamespace.py 2012-07-11 12:28:19 +0000
120@@ -44,7 +44,11 @@
121 )
122 from lp.code.interfaces.branchtarget import IBranchTarget
123 from lp.code.model.branch import Branch
124-from lp.registry.enums import InformationType
125+from lp.registry.enums import (
126+ InformationType,
127+ PRIVATE_INFORMATION_TYPES,
128+ PUBLIC_INFORMATION_TYPES,
129+ )
130 from lp.registry.errors import (
131 NoSuchDistroSeries,
132 NoSuchSourcePackageName,
133@@ -168,7 +172,7 @@
134 "%s cannot create branches owned by %s"
135 % (registrant.displayname, owner.displayname))
136
137- if not self.checkCreationPolicy(registrant):
138+ if not self.getAllowedInformationTypes():
139 raise BranchCreationForbidden(
140 'You cannot create branches in "%s"' % self.name)
141
142@@ -261,30 +265,18 @@
143 else:
144 return True
145
146+ def getAllowedInformationTypes(self):
147+ """See `IBranchNamespace`."""
148+ raise NotImplementedError
149+
150 def areNewBranchesPrivate(self):
151 """See `IBranchNamespace`."""
152- # Always delegates to canBranchesBePrivate for now.
153- return self.canBranchesBePrivate()
154-
155- def canBranchesBePrivate(self):
156- """See `IBranchNamespace`."""
157- raise NotImplementedError(self.canBranchesBePrivate)
158-
159- def canBranchesBePublic(self):
160- """See `IBranchNamespace`."""
161- raise NotImplementedError(self.canBranchesBePublic)
162+ return InformationType.USERDATA in self.getAllowedInformationTypes()
163
164 def getPrivacySubscriber(self):
165 """See `IBranchNamespace`."""
166 raise NotImplementedError(self.getPrivacySubscriber)
167
168- def checkCreationPolicy(self, user):
169- """Check to see if user is allowed a branch in this namespace.
170-
171- :return: True if the user is allowed, False otherwise.
172- """
173- raise NotImplementedError(self.checkCreationPolicy)
174-
175
176 class PersonalNamespace(_BaseNamespace):
177 """A namespace for personal (or 'junk') branches.
178@@ -307,26 +299,19 @@
179 """See `IBranchNamespace`."""
180 return '~%s/+junk' % self.owner.name
181
182- def canBranchesBePrivate(self):
183- """See `IBranchNamespace`."""
184- private = False
185- if self.owner.is_team and (
186- self.owner.visibility == PersonVisibility.PRIVATE):
187- private = True
188- return private
189-
190- def canBranchesBePublic(self):
191- """See `IBranchNamespace`."""
192- return True
193+ def getAllowedInformationTypes(self):
194+ """See `IBranchNamespace`."""
195+ # Private teams get private branches, everyone else gets public ones.
196+ if (self.owner.is_team
197+ and self.owner.visibility == PersonVisibility.PRIVATE):
198+ return PUBLIC_INFORMATION_TYPES + PRIVATE_INFORMATION_TYPES
199+ else:
200+ return PUBLIC_INFORMATION_TYPES
201
202 def getPrivacySubscriber(self):
203 """See `IBranchNamespace`."""
204 return None
205
206- def checkCreationPolicy(self, user):
207- """See `_BaseNamespace`."""
208- return True
209-
210 @property
211 def target(self):
212 """See `IBranchNamespace`."""
213@@ -388,40 +373,39 @@
214 else:
215 return None
216
217- def checkCreationPolicy(self, user):
218- """See `_BaseNamespace`."""
219- if len(self._getRelatedPolicies()) > 0:
220- return True
221- base_rule = self.product.getBaseBranchVisibilityRule()
222- return base_rule == BranchVisibilityRule.PUBLIC
223-
224- def canBranchesBePrivate(self):
225+ def getAllowedInformationTypes(self):
226 """See `IBranchNamespace`."""
227- # If there is a rule for the namespace owner, use that.
228- private = (
229+ private_rules = (
230 BranchVisibilityRule.PRIVATE,
231 BranchVisibilityRule.PRIVATE_ONLY)
232- rule = self.product.getBranchVisibilityRuleForTeam(self.owner)
233- if rule is not None:
234- return rule in private
235- # If the owner is a member of any team that has a PRIVATE or
236- # PRIVATE_ONLY rule, then the branches are private.
237- return len(self._getRelatedPrivatePolicies()) > 0
238-
239- def canBranchesBePublic(self):
240- """See `IBranchNamespace`."""
241- # If there is an explicit rule for the namespace owner, use that.
242- rule = self.product.getBranchVisibilityRuleForTeam(self.owner)
243- if rule is not None:
244- return rule != BranchVisibilityRule.PRIVATE_ONLY
245- # If there is another policy that allows public, then branches can be
246- # public.
247- for policy in self._getRelatedPolicies():
248- if policy.rule != BranchVisibilityRule.PRIVATE_ONLY:
249- return True
250- # If the default is public, then we can have public branches.
251- base_rule = self.product.getBaseBranchVisibilityRule()
252- return base_rule == BranchVisibilityRule.PUBLIC
253+
254+ rule = self.product.getBranchVisibilityRuleForTeam(self.owner)
255+ if rule is not None:
256+ # If there is an explicit rule for the namespace owner, use that.
257+ private = rule in private_rules
258+ public = rule != BranchVisibilityRule.PRIVATE_ONLY
259+ else:
260+ # Otherwise find all the rules for the owner's teams.
261+ related_rules = set(p.rule for p in self._getRelatedPolicies())
262+
263+ # If any of the rules allow private branches, allow them.
264+ private = bool(related_rules.intersection(private_rules))
265+
266+ # If any of the rules allow public branches, allow them.
267+ if related_rules.difference([BranchVisibilityRule.PRIVATE_ONLY]):
268+ public = True
269+ else:
270+ # There's no team-specific rules, or none of them allow
271+ # public branches. Fall back to the default rule.
272+ base_rule = self.product.getBaseBranchVisibilityRule()
273+ public = base_rule == BranchVisibilityRule.PUBLIC
274+
275+ types = []
276+ if public:
277+ types.extend(PUBLIC_INFORMATION_TYPES)
278+ if private:
279+ types.extend(PRIVATE_INFORMATION_TYPES)
280+ return types
281
282
283 class PackageNamespace(_BaseNamespace):
284@@ -453,22 +437,14 @@
285 """See `IBranchNamespace`."""
286 return IBranchTarget(self.sourcepackage)
287
288- def canBranchesBePrivate(self):
289- """See `IBranchNamespace`."""
290- return False
291-
292- def canBranchesBePublic(self):
293- """See `IBranchNamespace`."""
294- return True
295+ def getAllowedInformationTypes(self):
296+ """See `IBranchNamespace`."""
297+ return PUBLIC_INFORMATION_TYPES
298
299 def getPrivacySubscriber(self):
300 """See `IBranchNamespace`."""
301 return None
302
303- def checkCreationPolicy(self, user):
304- """See `_BaseNamespace`."""
305- return True
306-
307
308 class BranchNamespaceSet:
309 """Only implementation of `IBranchNamespaceSet`."""
310
311=== modified file 'lib/lp/code/model/tests/test_branch.py'
312--- lib/lp/code/model/tests/test_branch.py 2012-07-09 00:18:47 +0000
313+++ lib/lp/code/model/tests/test_branch.py 2012-07-11 12:28:19 +0000
314@@ -54,8 +54,6 @@
315 )
316 from lp.code.errors import (
317 AlreadyLatestFormat,
318- BranchCannotBePrivate,
319- BranchCannotBePublic,
320 BranchCannotChangeInformationType,
321 BranchCreatorNotMemberOfOwnerTeam,
322 BranchCreatorNotOwner,
323@@ -2419,10 +2417,10 @@
324
325 def test_public_to_private_not_allowed(self):
326 # If there are no privacy policies allowing private branches, then
327- # BranchCannotBePrivate is rasied.
328+ # BranchCannotChangeInformationType is rasied.
329 branch = self.factory.makeProductBranch()
330 self.assertRaises(
331- BranchCannotBePrivate,
332+ BranchCannotChangeInformationType,
333 branch.setPrivate,
334 True, branch.owner)
335
336@@ -2460,7 +2458,8 @@
337
338 def test_private_to_public_not_allowed(self):
339 # If the namespace policy does not allow public branches, attempting
340- # to change the branch to be public raises BranchCannotBePublic.
341+ # to change the branch to be public raises
342+ # BranchCannotChangeInformationType.
343 branch = self.factory.makeProductBranch(
344 information_type=InformationType.USERDATA)
345 branch.product.setBranchVisibilityTeamPolicy(
346@@ -2468,7 +2467,7 @@
347 branch.product.setBranchVisibilityTeamPolicy(
348 branch.owner, BranchVisibilityRule.PRIVATE_ONLY)
349 self.assertRaises(
350- BranchCannotBePublic,
351+ BranchCannotChangeInformationType,
352 branch.setPrivate,
353 False, branch.owner)
354
355
356=== modified file 'lib/lp/code/model/tests/test_branchnamespace.py'
357--- lib/lp/code/model/tests/test_branchnamespace.py 2012-06-08 06:01:50 +0000
358+++ lib/lp/code/model/tests/test_branchnamespace.py 2012-07-11 12:28:19 +0000
359@@ -35,7 +35,11 @@
360 PersonalNamespace,
361 ProductNamespace,
362 )
363-from lp.registry.enums import InformationType
364+from lp.registry.enums import (
365+ InformationType,
366+ PRIVATE_INFORMATION_TYPES,
367+ PUBLIC_INFORMATION_TYPES,
368+ )
369 from lp.registry.errors import (
370 NoSuchDistroSeries,
371 NoSuchSourcePackageName,
372@@ -974,8 +978,8 @@
373 BranchVisibilityRule.PRIVATE_ONLY)
374
375
376-class TestPersonalNamespaceCanBranchesBePrivate(TestCaseWithFactory):
377- """Tests for PersonalNamespace.canBranchesBePrivate."""
378+class TestPersonalNamespaceAllowedInformationTypes(TestCaseWithFactory):
379+ """Tests for PersonalNamespace.getAllowedInformationTypes."""
380
381 layer = DatabaseFunctionalLayer
382
383@@ -983,61 +987,44 @@
384 # +junk branches are not private for individuals
385 person = self.factory.makePerson()
386 namespace = PersonalNamespace(person)
387- self.assertFalse(namespace.canBranchesBePrivate())
388+ self.assertContentEqual(
389+ PUBLIC_INFORMATION_TYPES,
390+ namespace.getAllowedInformationTypes())
391
392 def test_public_team(self):
393 # +junk branches for public teams cannot be private
394 team = self.factory.makeTeam()
395 namespace = PersonalNamespace(team)
396- self.assertFalse(namespace.canBranchesBePrivate())
397+ self.assertContentEqual(
398+ PUBLIC_INFORMATION_TYPES,
399+ namespace.getAllowedInformationTypes())
400
401 def test_private_team(self):
402- # +junk branches can be private for private teams
403+ # +junk branches can be private or public for private teams
404 team = self.factory.makeTeam(visibility=PersonVisibility.PRIVATE)
405 namespace = PersonalNamespace(team)
406- self.assertTrue(namespace.canBranchesBePrivate())
407-
408-
409-class TestPersonalNamespaceCanBranchesBePublic(TestCaseWithFactory):
410- """Tests for PersonalNamespace.canBranchesBePublic."""
411-
412- layer = DatabaseFunctionalLayer
413-
414- def test_anyone(self):
415- # All +junk branches are public.
416- person = self.factory.makePerson()
417- namespace = PersonalNamespace(person)
418- self.assertTrue(namespace.canBranchesBePublic())
419-
420-
421-class TestPackageNamespaceCanBranchesBePrivate(TestCaseWithFactory):
422- """Tests for PackageNamespace.canBranchesBePrivate."""
423-
424- layer = DatabaseFunctionalLayer
425-
426- def test_anyone(self):
427- # No source package branches are private.
428- source_package = self.factory.makeSourcePackage()
429- person = self.factory.makePerson()
430- namespace = PackageNamespace(person, source_package)
431- self.assertFalse(namespace.canBranchesBePrivate())
432-
433-
434-class TestPackageNamespaceCanBranchesBePublic(TestCaseWithFactory):
435- """Tests for PackageNamespace.canBranchesBePublic."""
436-
437- layer = DatabaseFunctionalLayer
438-
439- def test_anyone(self):
440- # All source package branches are public.
441- source_package = self.factory.makeSourcePackage()
442- person = self.factory.makePerson()
443- namespace = PackageNamespace(person, source_package)
444- self.assertTrue(namespace.canBranchesBePublic())
445-
446-
447-class TestProductNamespaceCanBranchesBePrivate(TestCaseWithFactory):
448- """Tests for ProductNamespace.canBranchesBePrivate."""
449+ self.assertContentEqual(
450+ PUBLIC_INFORMATION_TYPES + PRIVATE_INFORMATION_TYPES,
451+ namespace.getAllowedInformationTypes())
452+
453+
454+class TestPackageNamespaceAllowedInformationTypes(TestCaseWithFactory):
455+ """Tests for PackageNamespace.getAllowedInformationTypes."""
456+
457+ layer = DatabaseFunctionalLayer
458+
459+ def test_anyone(self):
460+ # Source package branches are always public.
461+ source_package = self.factory.makeSourcePackage()
462+ person = self.factory.makePerson()
463+ namespace = PackageNamespace(person, source_package)
464+ self.assertContentEqual(
465+ PUBLIC_INFORMATION_TYPES,
466+ namespace.getAllowedInformationTypes())
467+
468+
469+class TestProductNamespaceAllowedInformationTypes(TestCaseWithFactory):
470+ """Tests for ProductNamespace.getAllowedInformationTypes."""
471
472 layer = DatabaseFunctionalLayer
473
474@@ -1048,33 +1035,26 @@
475 def _getNamespace(self, owner):
476 return ProductNamespace(owner, self.product)
477
478- def assertNewBranchesPublic(self, owner):
479- # Assert that new branches in the owner namespace are public.
480- namespace = self._getNamespace(owner)
481- self.assertFalse(namespace.canBranchesBePrivate())
482-
483- def assertNewBranchesPrivate(self, owner):
484- # Assert that new branches in the owner namespace are private.
485- namespace = self._getNamespace(owner)
486- self.assertTrue(namespace.canBranchesBePrivate())
487+ def assertTypes(self, owner, types):
488+ namespace = self._getNamespace(owner)
489+ self.assertContentEqual(types, namespace.getAllowedInformationTypes())
490
491 def test_no_policies(self):
492 # If there are no defined policies, any personal branch is not
493 # private.
494- self.assertNewBranchesPublic(self.factory.makePerson())
495+ self.assertTypes(self.factory.makePerson(), PUBLIC_INFORMATION_TYPES)
496
497 def test_any_person_with_public_base_rule(self):
498 # If the base visibility rule is PUBLIC, then new branches are public.
499 self.product.setBranchVisibilityTeamPolicy(
500 None, BranchVisibilityRule.PUBLIC)
501- self.assertNewBranchesPublic(self.factory.makePerson())
502+ self.assertTypes(self.factory.makePerson(), PUBLIC_INFORMATION_TYPES)
503
504 def test_any_person_with_forbidden_base_rule(self):
505- # If the base visibility rule is FORBIDDEN, new branches are still
506- # considered public.
507+ # If the base visibility rule is FORBIDDEN, there are no legal types.
508 self.product.setBranchVisibilityTeamPolicy(
509 None, BranchVisibilityRule.FORBIDDEN)
510- self.assertNewBranchesPublic(self.factory.makePerson())
511+ self.assertTypes(self.factory.makePerson(), [])
512
513 def test_team_member_with_private_rule(self):
514 # If a person is a member of a team that has a PRIVATE rule, then new
515@@ -1083,8 +1063,10 @@
516 team = self.factory.makeTeam(owner=person)
517 self.product.setBranchVisibilityTeamPolicy(
518 team, BranchVisibilityRule.PRIVATE)
519- self.assertNewBranchesPrivate(person)
520- self.assertNewBranchesPrivate(team)
521+ self.assertTypes(
522+ person, PUBLIC_INFORMATION_TYPES + PRIVATE_INFORMATION_TYPES)
523+ self.assertTypes(
524+ team, PUBLIC_INFORMATION_TYPES + PRIVATE_INFORMATION_TYPES)
525
526 def test_team_member_with_private_only_rule(self):
527 # If a person is a member of a team that has a PRIVATE_ONLY rule, then
528@@ -1092,9 +1074,11 @@
529 person = self.factory.makePerson()
530 team = self.factory.makeTeam(owner=person)
531 self.product.setBranchVisibilityTeamPolicy(
532+ None, BranchVisibilityRule.FORBIDDEN)
533+ self.product.setBranchVisibilityTeamPolicy(
534 team, BranchVisibilityRule.PRIVATE_ONLY)
535- self.assertNewBranchesPrivate(person)
536- self.assertNewBranchesPrivate(team)
537+ self.assertTypes(person, PRIVATE_INFORMATION_TYPES)
538+ self.assertTypes(team, PRIVATE_INFORMATION_TYPES)
539
540 def test_non_team_member_with_private_rule(self):
541 # If a person is a not a member of a team that has a privacy rule,
542@@ -1103,7 +1087,7 @@
543 team = self.factory.makeTeam(owner=person)
544 self.product.setBranchVisibilityTeamPolicy(
545 team, BranchVisibilityRule.PRIVATE)
546- self.assertNewBranchesPublic(self.factory.makePerson())
547+ self.assertTypes(self.factory.makePerson(), PUBLIC_INFORMATION_TYPES)
548
549 def test_team_member_with_multiple_private_rules(self):
550 # If a person is a member of multiple teams that has a privacy rules,
551@@ -1115,9 +1099,12 @@
552 team_1, BranchVisibilityRule.PRIVATE)
553 self.product.setBranchVisibilityTeamPolicy(
554 team_2, BranchVisibilityRule.PRIVATE)
555- self.assertNewBranchesPrivate(person)
556- self.assertNewBranchesPrivate(team_1)
557- self.assertNewBranchesPrivate(team_2)
558+ self.assertTypes(
559+ person, PUBLIC_INFORMATION_TYPES + PRIVATE_INFORMATION_TYPES)
560+ self.assertTypes(
561+ team_1, PUBLIC_INFORMATION_TYPES + PRIVATE_INFORMATION_TYPES)
562+ self.assertTypes(
563+ team_2, PUBLIC_INFORMATION_TYPES + PRIVATE_INFORMATION_TYPES)
564
565 def test_team_member_with_multiple_differing_private_rules(self):
566 # If a person is a member of multiple teams that has a privacy rules,
567@@ -1131,103 +1118,12 @@
568 private_team, BranchVisibilityRule.PRIVATE)
569 self.product.setBranchVisibilityTeamPolicy(
570 public_team, BranchVisibilityRule.PUBLIC)
571- self.assertNewBranchesPrivate(person)
572- self.assertNewBranchesPrivate(private_team)
573- self.assertNewBranchesPublic(public_team)
574-
575-
576-class TestProductNamespaceCanBranchesBePublic(TestCaseWithFactory):
577- """Tests for ProductNamespace.canBranchesBePublic."""
578-
579- layer = DatabaseFunctionalLayer
580-
581- def setUp(self):
582- TestCaseWithFactory.setUp(self)
583- self.product = self.factory.makeProduct()
584-
585- def _getNamespace(self, owner):
586- return ProductNamespace(owner, self.product)
587-
588- def assertBranchesCanBePublic(self, owner):
589- # Assert that branches can be public in the owner namespace.
590- namespace = self._getNamespace(owner)
591- self.assertTrue(namespace.canBranchesBePublic())
592-
593- def assertBranchesMustBePrivate(self, owner):
594- # Assert that branches must be private in the owner namespace.
595- namespace = self._getNamespace(owner)
596- self.assertFalse(namespace.canBranchesBePublic())
597-
598- def test_no_policies(self):
599- # If there are no defined policies, any branch can be public.
600- self.assertBranchesCanBePublic(self.factory.makePerson())
601-
602- def test_any_person_with_public_base_rule(self):
603- # If the base visibility rule is PUBLIC, any branch can be public
604- self.product.setBranchVisibilityTeamPolicy(
605- None, BranchVisibilityRule.PUBLIC)
606- self.assertBranchesCanBePublic(self.factory.makePerson())
607-
608- def test_any_person_with_forbidden_base_rule(self):
609- # If the base visibility rule is FORBIDDEN, branches must be private.
610- self.product.setBranchVisibilityTeamPolicy(
611- None, BranchVisibilityRule.FORBIDDEN)
612- self.assertBranchesMustBePrivate(self.factory.makePerson())
613-
614- def test_team_member_with_private_rule(self):
615- # If a person is a member of a team that has a PRIVATE rule then the
616- # branches can be public even though the default is FORBIDDEN.
617- person = self.factory.makePerson()
618- team = self.factory.makeTeam(owner=person)
619- self.product.setBranchVisibilityTeamPolicy(
620- None, BranchVisibilityRule.FORBIDDEN)
621- self.product.setBranchVisibilityTeamPolicy(
622- team, BranchVisibilityRule.PRIVATE)
623- self.assertBranchesCanBePublic(person)
624- self.assertBranchesCanBePublic(team)
625-
626- def test_team_member_with_private_only_rule(self):
627- # If a person is a member of a team that has a PRIVATE_ONLY rule, and
628- # the base rule is FORBIDDEN, then the branches must be private.
629- person = self.factory.makePerson()
630- team = self.factory.makeTeam(owner=person)
631- self.product.setBranchVisibilityTeamPolicy(
632- None, BranchVisibilityRule.FORBIDDEN)
633- self.product.setBranchVisibilityTeamPolicy(
634- team, BranchVisibilityRule.PRIVATE_ONLY)
635- self.assertBranchesMustBePrivate(person)
636- self.assertBranchesMustBePrivate(team)
637-
638- def test_team_member_with_private_only_rule_public_base_rule(self):
639- # If a person is a member of a team that has a PRIVATE_ONLY rule, and
640- # the base rule is PUBLIC, then the branches must be private in the
641- # team namespace, but can be public in the personal namespace.
642- person = self.factory.makePerson()
643- team = self.factory.makeTeam(owner=person)
644- self.product.setBranchVisibilityTeamPolicy(
645- None, BranchVisibilityRule.PUBLIC)
646- self.product.setBranchVisibilityTeamPolicy(
647- team, BranchVisibilityRule.PRIVATE_ONLY)
648- self.assertBranchesCanBePublic(person)
649- self.assertBranchesMustBePrivate(team)
650-
651- def test_team_member_with_multiple_private_rules(self):
652- # If a person is a member of multiple teams that has a privacy rules,
653- # then new branches must stay private in any namespace that defines
654- # PRIVATE_ONLY, but if the team member is a member of any teams that
655- # specify just PRIVATE, then branches can be made public.
656- person = self.factory.makePerson()
657- team_1 = self.factory.makeTeam(owner=person)
658- team_2 = self.factory.makeTeam(owner=person)
659- self.product.setBranchVisibilityTeamPolicy(
660- None, BranchVisibilityRule.FORBIDDEN)
661- self.product.setBranchVisibilityTeamPolicy(
662- team_1, BranchVisibilityRule.PRIVATE_ONLY)
663- self.product.setBranchVisibilityTeamPolicy(
664- team_2, BranchVisibilityRule.PRIVATE)
665- self.assertBranchesCanBePublic(person)
666- self.assertBranchesMustBePrivate(team_1)
667- self.assertBranchesCanBePublic(team_2)
668+ self.assertTypes(
669+ person, PUBLIC_INFORMATION_TYPES + PRIVATE_INFORMATION_TYPES)
670+ self.assertTypes(
671+ private_team,
672+ PUBLIC_INFORMATION_TYPES + PRIVATE_INFORMATION_TYPES)
673+ self.assertTypes(public_team, PUBLIC_INFORMATION_TYPES)
674
675
676 class BaseValidateNewBranchMixin:
677@@ -1389,7 +1285,8 @@
678 :param owner: The person or team that will be the owner of the branch.
679 """
680 namespace = get_branch_namespace(owner, product=self.product)
681- self.assertFalse(namespace.canBranchesBePrivate())
682+ self.assertNotIn(
683+ InformationType.USERDATA, namespace.getAllowedInformationTypes())
684
685 def assertPrivateSubscriber(self, creator, owner, subscriber):
686 """Assert that the policy check results in a private branch.
687@@ -1400,7 +1297,8 @@
688 """
689 policy = IBranchNamespacePolicy(
690 get_branch_namespace(owner, product=self.product))
691- self.assertTrue(policy.canBranchesBePrivate())
692+ self.assertIn(
693+ InformationType.USERDATA, policy.getAllowedInformationTypes())
694 if subscriber is None:
695 self.assertIs(None, policy.getPrivacySubscriber())
696 else: