1
=========================
2
Private team visibility
3
=========================
5
Private teams restrict the visibility of their attributes to select
6
sets of users in order to prevent leaking confidential data.
8
Private teams restrict the viewing of the membership list
9
to team administrators, other members of the team, and Launchpad
12
>>> from lp.registry.interfaces.person import PersonVisibility
13
>>> from lp.testing import login_celebrity
15
>>> priv_owner = factory.makePerson(name="priv-owner")
16
>>> priv_member = factory.makePerson(name="priv-member")
17
>>> commercial_admin = login_celebrity('commercial_admin')
18
>>> priv_team = factory.makeTeam(owner=priv_owner, name="priv-team",
19
... visibility=PersonVisibility.PRIVATE)
20
>>> login_person(priv_owner)
21
>>> ignored = priv_team.addMember(priv_member, reviewer=priv_owner)
23
The team owner can see the membership.
25
>>> members = priv_team.activemembers
26
>>> for member in members:
31
A team member can access the membership.
33
>>> login_person(priv_member)
34
>>> members = priv_team.activemembers
36
A commercial admin can view private teams and private team memberships.
38
>>> from canonical.launchpad.webapp.authorization import check_permission
40
>>> commercial_admin = login_celebrity('commercial_admin')
41
>>> check_permission('launchpad.View', priv_team)
43
>>> team_membership = priv_member.team_memberships[0]
44
>>> check_permission('launchpad.View', team_membership)
47
A person who is not in the team cannot see the membership and cannot
48
see other details of the team, such as the name.
50
>>> login('no-priv@canonical.com')
51
>>> members = priv_team.activemembers
52
Traceback (most recent call last):
54
Unauthorized: (<Person at ... priv-team (Priv Team)>,
55
'activemembers', 'launchpad.View')
57
>>> print priv_team.name
58
Traceback (most recent call last):
60
Unauthorized: (<Person at ... priv-team (Priv Team)>,
61
'name', 'launchpad.LimitedView')
63
Public teams can join private teams. When adding one team to another
64
the team is invited to join and that invitation must be accepted by
65
one of the invited team's admins. Normally the admin of the invited
66
team is not a member of the private team and therefore cannot even see
67
the page to accept the invitation! To resolve that situation the
68
rules for viewing a private team include admins of invited teams.
70
>>> pub_owner = factory.makePerson(name="pub-owner")
71
>>> pub_member = factory.makePerson(name="pub-member")
72
>>> pub_team = factory.makeTeam(owner=pub_owner, name="pubteam")
73
>>> login_person(pub_owner)
74
>>> ignored = pub_team.addMember(pub_member, reviewer=pub_owner)
76
At this point the public team owner cannot see the priv-team's bits.
78
>>> print priv_team.name
79
Traceback (most recent call last):
81
Unauthorized: (<Person at ... priv-team (Priv Team)>,
82
'name', 'launchpad.LimitedView')
84
>>> login_person(priv_owner)
85
>>> ignored = priv_team.addMember(pub_team, reviewer=priv_owner)
87
The public team is not yet a member of the priv-team.
89
>>> pub_team in priv_team.activemembers
91
>>> pub_owner in priv_team.activemembers
94
The public team's owner can now see the priv-team's bits since his team
95
has been invited to join.
97
>>> login_person(pub_owner)
98
>>> print priv_team.name
101
But a non-admin member of the public team still cannot see anything
104
>>> login_person(pub_member)
105
>>> print priv_team.name
106
Traceback (most recent call last):
108
Unauthorized: (<Person at ... priv-team (Priv Team)>,
109
'name', 'launchpad.LimitedView')
111
A person with visibility to any of the branches owned by the private team will
112
be granted limited view permission on the team.
114
For private branches, a user needs to be subscribed to the branch for the
115
branch (and hence team) to be visible.
117
>>> login_person(priv_owner)
118
>>> private_team_branch = factory.makeBranch(
119
... owner=priv_team, private=True)
120
>>> login_person(pub_member)
121
>>> check_permission('launchpad.LimitedView', priv_team)
124
>>> login_person(priv_owner)
125
>>> sub = factory.makeBranchSubscription(
126
... branch=private_team_branch, person=pub_member,
127
... subscribed_by=priv_owner)
129
>>> login_person(pub_member)
130
>>> check_permission('launchpad.LimitedView', priv_team)
133
User who can see a branch can also see private teams for which reviews have
135
>>> some_person = factory.makePerson()
136
>>> login_person(priv_owner)
137
>>> product = factory.makeProduct()
138
>>> target_branch = factory.makeBranch(
139
... owner=priv_owner, private=True, product=product)
140
>>> source_branch = factory.makeBranch(
141
... owner=priv_owner, product=product)
142
>>> bmp = factory.makeBranchMergeProposal(
143
... source_branch=source_branch, target_branch=target_branch,
144
... reviewer=priv_team, registrant=priv_owner)
145
>>> login_person(some_person)
146
>>> check_permission('launchpad.LimitedView', priv_team)
148
>>> login_person(priv_owner)
149
>>> sub = factory.makeBranchSubscription(
150
... branch=target_branch, person=some_person,
151
... subscribed_by=priv_owner)
153
>>> login_person(some_person)
154
>>> check_permission('launchpad.LimitedView', priv_team)
157
Subscribers to the teams private PPA have limited view permission.
159
>>> login_person(priv_owner)
160
>>> archive = factory.makeArchive(private=True, owner=priv_team)
161
>>> archive_subscriber = factory.makePerson()
162
>>> sub = archive.newSubscription(
163
... archive_subscriber, registrant=archive.owner)
165
>>> login_person(archive_subscriber)
166
>>> check_permission('launchpad.LimitedView', priv_team)
169
Users with LimitedView can know identifying information like name,
170
displayname, and unique_name, but cannot know other information like
173
>>> print priv_team.name
176
>>> print priv_team.displayname
179
>>> print priv_team.unique_displayname
180
Priv Team (priv-team)
182
>>> print priv_team.icon
185
>>> print priv_team.allmembers
186
Traceback (most recent call last):
188
Unauthorized: (<Person at ... priv-team (Priv Team)>,
189
'allmembers', 'launchpad.View')
191
Anonymous users do not have permission.
193
>>> check_permission('launchpad.LimitedView', priv_team)
196
A team owner must be able to access the team even if they are not a team
197
member. When a team is created, the owner is automatically made an admin
198
member. So we revoke that membership and check that they still have access.
199
>>> from lp.registry.interfaces.teammembership import (
200
... ITeamMembershipSet,
201
... TeamMembershipStatus,
203
>>> membership_set = getUtility(ITeamMembershipSet)
204
>>> login_person(priv_owner)
205
>>> tm = membership_set.getByPersonAndTeam(priv_owner, priv_team)
206
>>> tm.setStatus(TeamMembershipStatus.DEACTIVATED, priv_owner)
208
>>> priv_owner.inTeam(priv_team)
210
>>> check_permission('launchpad.View', priv_team)