Merge ~pappacena/launchpad:snap-pillar-subscribe-removal-job into launchpad:master
- Git
- lp:~pappacena/launchpad
- snap-pillar-subscribe-removal-job
- Merge into master
Status: | Superseded | ||||
---|---|---|---|---|---|
Proposed branch: | ~pappacena/launchpad:snap-pillar-subscribe-removal-job | ||||
Merge into: | launchpad:master | ||||
Prerequisite: | ~pappacena/launchpad:snap-pillar-subscribe | ||||
Diff against target: |
890 lines (+199/-85) 16 files modified
database/schema/security.cfg (+2/-0) lib/lp/blueprints/model/specification.py (+2/-2) lib/lp/blueprints/tests/test_specification.py (+4/-4) lib/lp/bugs/model/bug.py (+3/-3) lib/lp/code/browser/branchsubscription.py (+2/-2) lib/lp/code/browser/gitsubscription.py (+2/-2) lib/lp/code/model/branch.py (+2/-2) lib/lp/code/model/gitrepository.py (+1/-1) lib/lp/code/model/tests/test_branchsubscription.py (+3/-3) lib/lp/registry/model/sharingjob.py (+36/-1) lib/lp/registry/services/sharingservice.py (+15/-12) lib/lp/registry/services/tests/test_sharingservice.py (+11/-7) lib/lp/registry/tests/test_sharingjob.py (+56/-10) lib/lp/snappy/interfaces/snap.py (+4/-0) lib/lp/snappy/model/snap.py (+36/-12) lib/lp/snappy/tests/test_snap.py (+20/-24) |
||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Colin Watson (community) | Approve | ||
Review via email: mp+398318@code.launchpad.net |
This proposal has been superseded by a proposal from 2021-03-11.
Commit message
Remove dangling SnapSubscription when changing Snap pillar's sharing policy
Description of the change
Thiago F. Pappacena (pappacena) : | # |
Colin Watson (cjwatson) : | # |
- 6ead4b4... by Thiago F. Pappacena
-
Merge branch 'snap-pillar-
subscribe' into snap-pillar- subscribe- removal- job - 96846ab... by Thiago F. Pappacena
-
Fixing snap privacy filter usage
- be29706... by Thiago F. Pappacena
-
Merge branch 'snap-pillar-
subscribe' into snap-pillar- subscribe- removal- job - 0efaed4... by Thiago F. Pappacena
-
Merge branch 'snap-pillar-
subscribe' into snap-pillar- subscribe- removal- job - d256e68... by Thiago F. Pappacena
-
Merge branch 'snap-pillar-
subscribe' into snap-pillar- subscribe- removal- job
Colin Watson (cjwatson) : | # |
- 76b720d... by Thiago F. Pappacena
-
Merge branch 'snap-pillar-
subscribe' into snap-pillar- subscribe- removal- job - e857291... by Thiago F. Pappacena
-
Refactoring and setting proper db permission for job
Thiago F. Pappacena (pappacena) wrote : | # |
Colin Watson (cjwatson) : | # |
- 920b88c... by Thiago F. Pappacena
-
Not granting commercial admin view permisson on every snap
Thiago F. Pappacena (pappacena) wrote : | # |
Pushed the changes for admin visibility after talking to wgrant and cjwatson.
Colin Watson (cjwatson) : | # |
- df76888... by Thiago F. Pappacena
-
Merge branch 'master' into snap-pillar-
subscribe- removal- job - 5f729ee... by Thiago F. Pappacena
-
Removing unecessary shortcut for admin permission on snaps
Thiago F. Pappacena (pappacena) : | # |
Unmerged commits
- 5f729ee... by Thiago F. Pappacena
-
Removing unecessary shortcut for admin permission on snaps
- df76888... by Thiago F. Pappacena
-
Merge branch 'master' into snap-pillar-
subscribe- removal- job - 920b88c... by Thiago F. Pappacena
-
Not granting commercial admin view permisson on every snap
- e857291... by Thiago F. Pappacena
-
Refactoring and setting proper db permission for job
- 76b720d... by Thiago F. Pappacena
-
Merge branch 'snap-pillar-
subscribe' into snap-pillar- subscribe- removal- job - d256e68... by Thiago F. Pappacena
-
Merge branch 'snap-pillar-
subscribe' into snap-pillar- subscribe- removal- job - 0efaed4... by Thiago F. Pappacena
-
Merge branch 'snap-pillar-
subscribe' into snap-pillar- subscribe- removal- job - be29706... by Thiago F. Pappacena
-
Merge branch 'snap-pillar-
subscribe' into snap-pillar- subscribe- removal- job - 96846ab... by Thiago F. Pappacena
-
Fixing snap privacy filter usage
- 6ead4b4... by Thiago F. Pappacena
-
Merge branch 'snap-pillar-
subscribe' into snap-pillar- subscribe- removal- job
Preview Diff
1 | diff --git a/database/schema/security.cfg b/database/schema/security.cfg |
2 | index e9dcc62..2f4ffdf 100644 |
3 | --- a/database/schema/security.cfg |
4 | +++ b/database/schema/security.cfg |
5 | @@ -2111,6 +2111,8 @@ public.job = SELECT, INSERT, UPDATE |
6 | public.person = SELECT |
7 | public.product = SELECT |
8 | public.sharingjob = SELECT, INSERT, UPDATE |
9 | +public.snap = SELECT |
10 | +public.snapsubscription = SELECT, UPDATE, DELETE |
11 | public.specification = SELECT |
12 | public.specificationsubscription = SELECT, DELETE |
13 | public.teamparticipation = SELECT |
14 | diff --git a/lib/lp/blueprints/model/specification.py b/lib/lp/blueprints/model/specification.py |
15 | index e0d4001..55ce9d5 100644 |
16 | --- a/lib/lp/blueprints/model/specification.py |
17 | +++ b/lib/lp/blueprints/model/specification.py |
18 | @@ -1,4 +1,4 @@ |
19 | -# Copyright 2009-2020 Canonical Ltd. This software is licensed under the |
20 | +# Copyright 2009-2021 Canonical Ltd. This software is licensed under the |
21 | # GNU Affero General Public License version 3 (see the file LICENSE). |
22 | |
23 | __metaclass__ = type |
24 | @@ -755,7 +755,7 @@ class Specification(SQLBase, BugLinkTargetMixin, InformationTypeMixin): |
25 | # Grant the subscriber access if they can't see the |
26 | # specification. |
27 | service = getUtility(IService, 'sharing') |
28 | - _, _, _, shared_specs = service.getVisibleArtifacts( |
29 | + _, _, _, _, shared_specs = service.getVisibleArtifacts( |
30 | person, specifications=[self], ignore_permissions=True) |
31 | if not shared_specs: |
32 | service.ensureAccessGrants( |
33 | diff --git a/lib/lp/blueprints/tests/test_specification.py b/lib/lp/blueprints/tests/test_specification.py |
34 | index 8de08c9..86c4e4a 100644 |
35 | --- a/lib/lp/blueprints/tests/test_specification.py |
36 | +++ b/lib/lp/blueprints/tests/test_specification.py |
37 | @@ -1,4 +1,4 @@ |
38 | -# Copyright 2010-2015 Canonical Ltd. This software is licensed under the |
39 | +# Copyright 2010-2021 Canonical Ltd. This software is licensed under the |
40 | # GNU Affero General Public License version 3 (see the file LICENSE). |
41 | |
42 | """Unit tests for Specification.""" |
43 | @@ -492,7 +492,7 @@ class SpecificationTests(TestCaseWithFactory): |
44 | product=product, information_type=InformationType.PROPRIETARY) |
45 | spec.subscribe(user, subscribed_by=owner) |
46 | service = getUtility(IService, 'sharing') |
47 | - _, _, _, shared_specs = service.getVisibleArtifacts( |
48 | + _, _, _, _, shared_specs = service.getVisibleArtifacts( |
49 | user, specifications=[spec]) |
50 | self.assertEqual([spec], shared_specs) |
51 | # The spec is also returned by getSharedSpecifications(), |
52 | @@ -509,7 +509,7 @@ class SpecificationTests(TestCaseWithFactory): |
53 | service.sharePillarInformation( |
54 | product, user_2, owner, permissions) |
55 | spec.subscribe(user_2, subscribed_by=owner) |
56 | - _, _, _, shared_specs = service.getVisibleArtifacts( |
57 | + _, _, _, _, shared_specs = service.getVisibleArtifacts( |
58 | user_2, specifications=[spec]) |
59 | self.assertEqual([spec], shared_specs) |
60 | self.assertEqual( |
61 | @@ -529,7 +529,7 @@ class SpecificationTests(TestCaseWithFactory): |
62 | spec.subscribe(user, subscribed_by=owner) |
63 | spec.unsubscribe(user, unsubscribed_by=owner) |
64 | service = getUtility(IService, 'sharing') |
65 | - _, _, _, shared_specs = service.getVisibleArtifacts( |
66 | + _, _, _, _, shared_specs = service.getVisibleArtifacts( |
67 | user, specifications=[spec]) |
68 | self.assertEqual([], shared_specs) |
69 | |
70 | diff --git a/lib/lp/bugs/model/bug.py b/lib/lp/bugs/model/bug.py |
71 | index a9b177c..f7ebc86 100644 |
72 | --- a/lib/lp/bugs/model/bug.py |
73 | +++ b/lib/lp/bugs/model/bug.py |
74 | @@ -1,4 +1,4 @@ |
75 | -# Copyright 2009-2020 Canonical Ltd. This software is licensed under the |
76 | +# Copyright 2009-2021 Canonical Ltd. This software is licensed under the |
77 | # GNU Affero General Public License version 3 (see the file LICENSE). |
78 | |
79 | """Launchpad bug-related database table classes.""" |
80 | @@ -875,7 +875,7 @@ class Bug(SQLBase, InformationTypeMixin): |
81 | # there is at least one bugtask for which access can be checked. |
82 | if self.default_bugtask: |
83 | service = getUtility(IService, 'sharing') |
84 | - bugs, _, _, _ = service.getVisibleArtifacts( |
85 | + bugs, _, _, _, _ = service.getVisibleArtifacts( |
86 | person, bugs=[self], ignore_permissions=True) |
87 | if not bugs: |
88 | service.ensureAccessGrants( |
89 | @@ -1819,7 +1819,7 @@ class Bug(SQLBase, InformationTypeMixin): |
90 | if information_type in PRIVATE_INFORMATION_TYPES: |
91 | service = getUtility(IService, 'sharing') |
92 | for person in (who, self.owner): |
93 | - bugs, _, _, _ = service.getVisibleArtifacts( |
94 | + bugs, _, _, _, _ = service.getVisibleArtifacts( |
95 | person, bugs=[self], ignore_permissions=True) |
96 | if not bugs: |
97 | # subscribe() isn't sufficient if a subscription |
98 | diff --git a/lib/lp/code/browser/branchsubscription.py b/lib/lp/code/browser/branchsubscription.py |
99 | index fbd98bc..cee4504 100644 |
100 | --- a/lib/lp/code/browser/branchsubscription.py |
101 | +++ b/lib/lp/code/browser/branchsubscription.py |
102 | @@ -1,4 +1,4 @@ |
103 | -# Copyright 2009-2020 Canonical Ltd. This software is licensed under the |
104 | +# Copyright 2009-2021 Canonical Ltd. This software is licensed under the |
105 | # GNU Affero General Public License version 3 (see the file LICENSE). |
106 | |
107 | __metaclass__ = type |
108 | @@ -276,7 +276,7 @@ class BranchSubscriptionEditView(LaunchpadEditFormView): |
109 | url = canonical_url(self.branch) |
110 | # If the subscriber can no longer see the branch, redirect them away. |
111 | service = getUtility(IService, 'sharing') |
112 | - _, branches, _, _ = service.getVisibleArtifacts( |
113 | + _, branches, _, _, _ = service.getVisibleArtifacts( |
114 | self.person, branches=[self.branch], ignore_permissions=True) |
115 | if not branches: |
116 | url = canonical_url(self.branch.target) |
117 | diff --git a/lib/lp/code/browser/gitsubscription.py b/lib/lp/code/browser/gitsubscription.py |
118 | index 3eda78c..a18d593 100644 |
119 | --- a/lib/lp/code/browser/gitsubscription.py |
120 | +++ b/lib/lp/code/browser/gitsubscription.py |
121 | @@ -1,4 +1,4 @@ |
122 | -# Copyright 2015-2018 Canonical Ltd. This software is licensed under the |
123 | +# Copyright 2015-2021 Canonical Ltd. This software is licensed under the |
124 | # GNU Affero General Public License version 3 (see the file LICENSE). |
125 | |
126 | __metaclass__ = type |
127 | @@ -280,7 +280,7 @@ class GitSubscriptionEditView(LaunchpadEditFormView): |
128 | # If the subscriber can no longer see the repository, redirect them |
129 | # away. |
130 | service = getUtility(IService, "sharing") |
131 | - _, _, repositories, _ = service.getVisibleArtifacts( |
132 | + _, _, repositories, _, _ = service.getVisibleArtifacts( |
133 | self.person, gitrepositories=[self.repository], |
134 | ignore_permissions=True) |
135 | if not repositories: |
136 | diff --git a/lib/lp/code/model/branch.py b/lib/lp/code/model/branch.py |
137 | index 947aaf1..278db40 100644 |
138 | --- a/lib/lp/code/model/branch.py |
139 | +++ b/lib/lp/code/model/branch.py |
140 | @@ -1,4 +1,4 @@ |
141 | -# Copyright 2009-2020 Canonical Ltd. This software is licensed under the |
142 | +# Copyright 2009-2021 Canonical Ltd. This software is licensed under the |
143 | # GNU Affero General Public License version 3 (see the file LICENSE). |
144 | |
145 | __metaclass__ = type |
146 | @@ -1041,7 +1041,7 @@ class Branch(SQLBase, WebhookTargetMixin, BzrIdentityMixin): |
147 | subscription.review_level = code_review_level |
148 | # Grant the subscriber access if they can't see the branch. |
149 | service = getUtility(IService, 'sharing') |
150 | - _, branches, _, _ = service.getVisibleArtifacts( |
151 | + _, branches, _, _, _ = service.getVisibleArtifacts( |
152 | person, branches=[self], ignore_permissions=True) |
153 | if not branches: |
154 | service.ensureAccessGrants( |
155 | diff --git a/lib/lp/code/model/gitrepository.py b/lib/lp/code/model/gitrepository.py |
156 | index 74d94ec..589dcbf 100644 |
157 | --- a/lib/lp/code/model/gitrepository.py |
158 | +++ b/lib/lp/code/model/gitrepository.py |
159 | @@ -1002,7 +1002,7 @@ class GitRepository(StormBase, WebhookTargetMixin, GitIdentityMixin): |
160 | subscription.review_level = code_review_level |
161 | # Grant the subscriber access if they can't see the repository. |
162 | service = getUtility(IService, "sharing") |
163 | - _, _, repositories, _ = service.getVisibleArtifacts( |
164 | + _, _, repositories, _, _ = service.getVisibleArtifacts( |
165 | person, gitrepositories=[self], ignore_permissions=True) |
166 | if not repositories: |
167 | service.ensureAccessGrants( |
168 | diff --git a/lib/lp/code/model/tests/test_branchsubscription.py b/lib/lp/code/model/tests/test_branchsubscription.py |
169 | index 6a15cd0..b5b234e 100644 |
170 | --- a/lib/lp/code/model/tests/test_branchsubscription.py |
171 | +++ b/lib/lp/code/model/tests/test_branchsubscription.py |
172 | @@ -1,4 +1,4 @@ |
173 | -# Copyright 2010-2017 Canonical Ltd. This software is licensed under the |
174 | +# Copyright 2010-2021 Canonical Ltd. This software is licensed under the |
175 | # GNU Affero General Public License version 3 (see the file LICENSE). |
176 | |
177 | """Tests for the BranchSubscription model object.""" |
178 | @@ -134,7 +134,7 @@ class TestBranchSubscriptions(TestCaseWithFactory): |
179 | None, CodeReviewNotificationLevel.NOEMAIL, owner) |
180 | # The stacked on branch should be visible. |
181 | service = getUtility(IService, 'sharing') |
182 | - _, visible_branches, _, _ = service.getVisibleArtifacts( |
183 | + _, visible_branches, _, _, _ = service.getVisibleArtifacts( |
184 | grantee, branches=[private_stacked_on_branch]) |
185 | self.assertContentEqual( |
186 | [private_stacked_on_branch], visible_branches) |
187 | @@ -162,7 +162,7 @@ class TestBranchSubscriptions(TestCaseWithFactory): |
188 | grantee, BranchSubscriptionNotificationLevel.NOEMAIL, |
189 | None, CodeReviewNotificationLevel.NOEMAIL, owner) |
190 | # The stacked on branch should not be visible. |
191 | - _, visible_branches, _, _ = service.getVisibleArtifacts( |
192 | + _, visible_branches, _, _, _ = service.getVisibleArtifacts( |
193 | grantee, branches=[private_stacked_on_branch]) |
194 | self.assertContentEqual([], visible_branches) |
195 | self.assertIn( |
196 | diff --git a/lib/lp/registry/model/sharingjob.py b/lib/lp/registry/model/sharingjob.py |
197 | index 7d10fa9..81e6a9e 100644 |
198 | --- a/lib/lp/registry/model/sharingjob.py |
199 | +++ b/lib/lp/registry/model/sharingjob.py |
200 | @@ -1,4 +1,4 @@ |
201 | -# Copyright 2012-2020 Canonical Ltd. This software is licensed under the |
202 | +# Copyright 2012-2021 Canonical Ltd. This software is licensed under the |
203 | # GNU Affero General Public License version 3 (see the file LICENSE). |
204 | |
205 | """Job classes related to the sharing feature are in here.""" |
206 | @@ -91,6 +91,12 @@ from lp.services.job.model.job import ( |
207 | ) |
208 | from lp.services.job.runner import BaseRunnableJob |
209 | from lp.services.mail.sendmail import format_address_for_person |
210 | +from lp.snappy.interfaces.snap import ISnap |
211 | +from lp.snappy.model.snap import ( |
212 | + get_snap_privacy_filter, |
213 | + Snap, |
214 | + ) |
215 | +from lp.snappy.model.snapsubscription import SnapSubscription |
216 | |
217 | |
218 | class SharingJobType(DBEnumeratedType): |
219 | @@ -263,6 +269,7 @@ class RemoveArtifactSubscriptionsJob(SharingJobDerived): |
220 | bug_ids = [] |
221 | branch_ids = [] |
222 | gitrepository_ids = [] |
223 | + snap_ids = [] |
224 | specification_ids = [] |
225 | if artifacts: |
226 | for artifact in artifacts: |
227 | @@ -272,6 +279,8 @@ class RemoveArtifactSubscriptionsJob(SharingJobDerived): |
228 | branch_ids.append(artifact.id) |
229 | elif IGitRepository.providedBy(artifact): |
230 | gitrepository_ids.append(artifact.id) |
231 | + elif ISnap.providedBy(artifact): |
232 | + snap_ids.append(artifact.id) |
233 | elif ISpecification.providedBy(artifact): |
234 | specification_ids.append(artifact.id) |
235 | else: |
236 | @@ -284,6 +293,7 @@ class RemoveArtifactSubscriptionsJob(SharingJobDerived): |
237 | 'bug_ids': bug_ids, |
238 | 'branch_ids': branch_ids, |
239 | 'gitrepository_ids': gitrepository_ids, |
240 | + 'snap_ids': snap_ids, |
241 | 'specification_ids': specification_ids, |
242 | 'information_types': information_types, |
243 | 'requestor.id': requestor.id |
244 | @@ -320,6 +330,10 @@ class RemoveArtifactSubscriptionsJob(SharingJobDerived): |
245 | return self.metadata.get('gitrepository_ids', []) |
246 | |
247 | @property |
248 | + def snap_ids(self): |
249 | + return self.metadata.get('snap_ids', []) |
250 | + |
251 | + @property |
252 | def specification_ids(self): |
253 | return self.metadata.get('specification_ids', []) |
254 | |
255 | @@ -349,6 +363,7 @@ class RemoveArtifactSubscriptionsJob(SharingJobDerived): |
256 | 'bug_ids': self.bug_ids, |
257 | 'branch_ids': self.branch_ids, |
258 | 'gitrepository_ids': self.gitrepository_ids, |
259 | + 'snap_ids': self.snap_ids, |
260 | 'specification_ids': self.specification_ids, |
261 | 'pillar': getattr(self.pillar, 'name', None), |
262 | 'grantee': getattr(self.grantee, 'name', None) |
263 | @@ -365,6 +380,7 @@ class RemoveArtifactSubscriptionsJob(SharingJobDerived): |
264 | bug_filters = [] |
265 | branch_filters = [] |
266 | gitrepository_filters = [] |
267 | + snap_filters = [] |
268 | specification_filters = [] |
269 | |
270 | if self.branch_ids: |
271 | @@ -372,6 +388,8 @@ class RemoveArtifactSubscriptionsJob(SharingJobDerived): |
272 | if self.gitrepository_ids: |
273 | gitrepository_filters.append(GitRepository.id.is_in( |
274 | self.gitrepository_ids)) |
275 | + if self.snap_ids: |
276 | + snap_filters.append(Snap.id.is_in(self.snap_ids)) |
277 | if self.specification_ids: |
278 | specification_filters.append(Specification.id.is_in( |
279 | self.specification_ids)) |
280 | @@ -387,6 +405,8 @@ class RemoveArtifactSubscriptionsJob(SharingJobDerived): |
281 | gitrepository_filters.append( |
282 | GitRepository.information_type.is_in( |
283 | self.information_types)) |
284 | + snap_filters.append(Snap._information_type.is_in( |
285 | + self.information_types)) |
286 | specification_filters.append( |
287 | Specification.information_type.is_in( |
288 | self.information_types)) |
289 | @@ -423,6 +443,11 @@ class RemoveArtifactSubscriptionsJob(SharingJobDerived): |
290 | Select( |
291 | TeamParticipation.personID, |
292 | where=TeamParticipation.team == self.grantee))) |
293 | + snap_filters.append( |
294 | + In(SnapSubscription.person_id, |
295 | + Select( |
296 | + TeamParticipation.personID, |
297 | + where=TeamParticipation.team == self.grantee))) |
298 | specification_filters.append( |
299 | In(SpecificationSubscription.person_id, |
300 | Select( |
301 | @@ -466,6 +491,16 @@ class RemoveArtifactSubscriptionsJob(SharingJobDerived): |
302 | for sub in gitrepository_subscriptions: |
303 | sub.repository.unsubscribe( |
304 | sub.person, self.requestor, ignore_permissions=True) |
305 | + if snap_filters: |
306 | + snap_filters.append( |
307 | + Not(get_snap_privacy_filter(SnapSubscription.person_id))) |
308 | + snap_subscriptions = IStore(SnapSubscription).using( |
309 | + SnapSubscription, |
310 | + Join(Snap, Snap.id == SnapSubscription.snap_id) |
311 | + ).find(SnapSubscription, *snap_filters).config(distinct=True) |
312 | + for sub in snap_subscriptions: |
313 | + sub.snap.unsubscribe( |
314 | + sub.person, self.requestor, ignore_permissions=True) |
315 | if specification_filters: |
316 | specification_filters.append(Not(*get_specification_privacy_filter( |
317 | SpecificationSubscription.person_id))) |
318 | diff --git a/lib/lp/registry/services/sharingservice.py b/lib/lp/registry/services/sharingservice.py |
319 | index 01e90da..4909604 100644 |
320 | --- a/lib/lp/registry/services/sharingservice.py |
321 | +++ b/lib/lp/registry/services/sharingservice.py |
322 | @@ -81,10 +81,7 @@ from lp.services.webapp.authorization import ( |
323 | available_with_permission, |
324 | check_permission, |
325 | ) |
326 | -from lp.snappy.interfaces.snap import ( |
327 | - ISnap, |
328 | - ISnapSet, |
329 | - ) |
330 | +from lp.snappy.interfaces.snap import ISnapSet |
331 | |
332 | |
333 | @implementer(ISharingService) |
334 | @@ -332,6 +329,7 @@ class SharingService: |
335 | bug_ids = [] |
336 | branch_ids = [] |
337 | gitrepository_ids = [] |
338 | + snap_ids = [] |
339 | for bug in bugs or []: |
340 | if (not ignore_permissions |
341 | and not check_permission('launchpad.View', bug)): |
342 | @@ -344,9 +342,14 @@ class SharingService: |
343 | branch_ids.append(branch.id) |
344 | for gitrepository in gitrepositories or []: |
345 | if (not ignore_permissions |
346 | - and not check_permission('launchpad.View', gitrepository)): |
347 | + and not check_permission('launchpad.View', gitrepository)): |
348 | raise Unauthorized |
349 | gitrepository_ids.append(gitrepository.id) |
350 | + for snap in snaps or []: |
351 | + if (not ignore_permissions |
352 | + and not check_permission('launchpad.View', snap)): |
353 | + raise Unauthorized |
354 | + snap_ids.append(snap.id) |
355 | for spec in specifications or []: |
356 | if (not ignore_permissions |
357 | and not check_permission('launchpad.View', spec)): |
358 | @@ -376,6 +379,12 @@ class SharingService: |
359 | visible_gitrepositories = list( |
360 | wanted_gitrepositories.getRepositories()) |
361 | |
362 | + # Load the Snaps. |
363 | + visible_snaps = [] |
364 | + if snap_ids: |
365 | + visible_snaps = list(getUtility(ISnapSet).findByIds( |
366 | + snap_ids, visible_by_user=person)) |
367 | + |
368 | # Load the specifications. |
369 | visible_specs = [] |
370 | if specifications: |
371 | @@ -387,7 +396,7 @@ class SharingService: |
372 | |
373 | return ( |
374 | visible_bugs, visible_branches, visible_gitrepositories, |
375 | - visible_specs) |
376 | + visible_snaps, visible_specs) |
377 | |
378 | def getInvisibleArtifacts(self, person, bugs=None, branches=None, |
379 | gitrepositories=None): |
380 | @@ -800,12 +809,6 @@ class SharingService: |
381 | getUtility(IAccessArtifactGrantSource).revokeByArtifact( |
382 | artifacts_to_delete, [grantee]) |
383 | |
384 | - # XXX: Pappacena 2021-02-05: snaps should not trigger this job, |
385 | - # since we do not have a "SnapSubscription" yet. |
386 | - artifacts = [i for i in artifacts if not ISnap.providedBy(i)] |
387 | - if not artifacts: |
388 | - return |
389 | - |
390 | # Create a job to remove subscriptions for artifacts the grantee can no |
391 | # longer see. |
392 | return getUtility(IRemoveArtifactSubscriptionsJobSource).create( |
393 | diff --git a/lib/lp/registry/services/tests/test_sharingservice.py b/lib/lp/registry/services/tests/test_sharingservice.py |
394 | index 9d0e07c..8d94723 100644 |
395 | --- a/lib/lp/registry/services/tests/test_sharingservice.py |
396 | +++ b/lib/lp/registry/services/tests/test_sharingservice.py |
397 | @@ -1,4 +1,4 @@ |
398 | -# Copyright 2012-2015 Canonical Ltd. This software is licensed under the |
399 | +# Copyright 2012-2021 Canonical Ltd. This software is licensed under the |
400 | # GNU Affero General Public License version 3 (see the file LICENSE). |
401 | |
402 | __metaclass__ = type |
403 | @@ -1101,7 +1101,7 @@ class TestSharingService(TestCaseWithFactory): |
404 | # Check that grantees have expected access grants and subscriptions. |
405 | for person in [team_grantee, person_grantee]: |
406 | (visible_bugs, visible_branches, visible_gitrepositories, |
407 | - visible_specs) = ( |
408 | + visible_snaps, visible_specs) = ( |
409 | self.service.getVisibleArtifacts( |
410 | person, bugs=bugs, branches=branches, |
411 | gitrepositories=gitrepositories, |
412 | @@ -1133,7 +1133,7 @@ class TestSharingService(TestCaseWithFactory): |
413 | for bug in bugs or []: |
414 | self.assertNotIn(person, bug.getDirectSubscribers()) |
415 | (visible_bugs, visible_branches, visible_gitrepositories, |
416 | - visible_specs) = ( |
417 | + visible_snaps, visible_specs) = ( |
418 | self.service.getVisibleArtifacts( |
419 | person, bugs=bugs, branches=branches, |
420 | gitrepositories=gitrepositories)) |
421 | @@ -1783,7 +1783,8 @@ class TestSharingService(TestCaseWithFactory): |
422 | grantee, ignore, bugs, branches, gitrepositories, specs = ( |
423 | self._make_Artifacts()) |
424 | # Check the results. |
425 | - shared_bugs, shared_branches, shared_gitrepositories, shared_specs = ( |
426 | + (shared_bugs, shared_branches, shared_gitrepositories, |
427 | + shared_snaps, shared_specs) = ( |
428 | self.service.getVisibleArtifacts( |
429 | grantee, bugs=bugs, branches=branches, |
430 | gitrepositories=gitrepositories, specifications=specs)) |
431 | @@ -1797,7 +1798,8 @@ class TestSharingService(TestCaseWithFactory): |
432 | # user has a policy grant for the pillar of the specification. |
433 | _, owner, bugs, branches, gitrepositories, specs = ( |
434 | self._make_Artifacts()) |
435 | - shared_bugs, shared_branches, shared_gitrepositories, shared_specs = ( |
436 | + (shared_bugs, shared_branches, shared_gitrepositories, |
437 | + shared_snaps, shared_specs) = ( |
438 | self.service.getVisibleArtifacts( |
439 | owner, bugs=bugs, branches=branches, |
440 | gitrepositories=gitrepositories, specifications=specs)) |
441 | @@ -1840,7 +1842,8 @@ class TestSharingService(TestCaseWithFactory): |
442 | information_type=InformationType.USERDATA) |
443 | bugs.append(bug) |
444 | |
445 | - shared_bugs, shared_branches, shared_gitrepositories, shared_specs = ( |
446 | + (shared_bugs, shared_branches, shared_gitrepositories, |
447 | + visible_snaps, shared_specs) = ( |
448 | self.service.getVisibleArtifacts(grantee, bugs=bugs)) |
449 | self.assertContentEqual(bugs, shared_bugs) |
450 | |
451 | @@ -1848,7 +1851,8 @@ class TestSharingService(TestCaseWithFactory): |
452 | for x in range(0, 5): |
453 | change_callback(bugs[x], owner) |
454 | # Check the results. |
455 | - shared_bugs, shared_branches, shared_gitrepositories, shared_specs = ( |
456 | + (shared_bugs, shared_branches, shared_gitrepositories, |
457 | + visible_snaps, shared_specs) = ( |
458 | self.service.getVisibleArtifacts(grantee, bugs=bugs)) |
459 | self.assertContentEqual(bugs[5:], shared_bugs) |
460 | |
461 | diff --git a/lib/lp/registry/tests/test_sharingjob.py b/lib/lp/registry/tests/test_sharingjob.py |
462 | index 58fa5c1..32aec0f 100644 |
463 | --- a/lib/lp/registry/tests/test_sharingjob.py |
464 | +++ b/lib/lp/registry/tests/test_sharingjob.py |
465 | @@ -1,4 +1,4 @@ |
466 | -# Copyright 2012-2015 Canonical Ltd. This software is licensed under the |
467 | +# Copyright 2012-2021 Canonical Ltd. This software is licensed under the |
468 | # GNU Affero General Public License version 3 (see the file LICENSE). |
469 | |
470 | """Tests for SharingJobs.""" |
471 | @@ -39,6 +39,7 @@ from lp.services.features.testing import FeatureFixture |
472 | from lp.services.job.interfaces.job import JobStatus |
473 | from lp.services.job.tests import block_on_job |
474 | from lp.services.mail.sendmail import format_address_for_person |
475 | +from lp.snappy.interfaces.snap import SNAP_TESTING_FLAGS |
476 | from lp.testing import ( |
477 | login_person, |
478 | person_logged_in, |
479 | @@ -127,6 +128,16 @@ class SharingJobDerivedTestCase(TestCaseWithFactory): |
480 | 'for gitrepository_ids=[%d], requestor=%s>' |
481 | % (gitrepository.id, requestor.name), repr(job)) |
482 | |
483 | + def test_repr_snaps(self): |
484 | + requestor = self.factory.makePerson() |
485 | + snap = self.factory.makeSnap() |
486 | + job = getUtility(IRemoveArtifactSubscriptionsJobSource).create( |
487 | + requestor, artifacts=[snap]) |
488 | + self.assertEqual( |
489 | + '<REMOVE_ARTIFACT_SUBSCRIPTIONS job reconciling subscriptions ' |
490 | + 'for requestor=%s, snap_ids=[%d]>' |
491 | + % (requestor.name, snap.id), repr(job)) |
492 | + |
493 | def test_repr_specifications(self): |
494 | requestor = self.factory.makePerson() |
495 | specification = self.factory.makeSpecification() |
496 | @@ -241,9 +252,11 @@ class RemoveArtifactSubscriptionsJobTestCase(TestCaseWithFactory): |
497 | layer = CeleryJobLayer |
498 | |
499 | def setUp(self): |
500 | - self.useFixture(FeatureFixture({ |
501 | + features = { |
502 | 'jobs.celery.enabled_classes': 'RemoveArtifactSubscriptionsJob', |
503 | - })) |
504 | + } |
505 | + features.update(SNAP_TESTING_FLAGS) |
506 | + self.useFixture(FeatureFixture(features)) |
507 | super(RemoveArtifactSubscriptionsJobTestCase, self).setUp() |
508 | |
509 | def test_create(self): |
510 | @@ -315,6 +328,9 @@ class RemoveArtifactSubscriptionsJobTestCase(TestCaseWithFactory): |
511 | gitrepository = self.factory.makeGitRepository( |
512 | owner=owner, target=product, |
513 | information_type=InformationType.USERDATA) |
514 | + snap = self.factory.makeSnap( |
515 | + owner=owner, registrant=owner, project=product, |
516 | + information_type=InformationType.USERDATA) |
517 | specification = self.factory.makeSpecification( |
518 | owner=owner, product=product, |
519 | information_type=InformationType.PROPRIETARY) |
520 | @@ -332,6 +348,7 @@ class RemoveArtifactSubscriptionsJobTestCase(TestCaseWithFactory): |
521 | gitrepository.subscribe(artifact_indirect_grantee, |
522 | BranchSubscriptionNotificationLevel.NOEMAIL, None, |
523 | CodeReviewNotificationLevel.NOEMAIL, owner) |
524 | + snap.subscribe(artifact_indirect_grantee, owner) |
525 | # Subscribing somebody to a specification does not automatically |
526 | # create an artifact grant. |
527 | spec_artifact = self.factory.makeAccessArtifact(specification) |
528 | @@ -341,10 +358,11 @@ class RemoveArtifactSubscriptionsJobTestCase(TestCaseWithFactory): |
529 | specification.subscribe(artifact_indirect_grantee, owner) |
530 | |
531 | # pick one of the concrete artifacts (bug, branch, Git repository, |
532 | - # or spec) and subscribe the teams and persons. |
533 | + # snap, or spec) and subscribe the teams and persons. |
534 | concrete_artifact, get_pillars, get_subscribers = configure_test( |
535 | - bug, branch, gitrepository, specification, policy_team_grantee, |
536 | - policy_indirect_grantee, artifact_team_grantee, owner) |
537 | + bug, branch, gitrepository, snap, specification, |
538 | + policy_team_grantee, policy_indirect_grantee, |
539 | + artifact_team_grantee, owner) |
540 | |
541 | # Subscribing policy_team_grantee has created an artifact grant so we |
542 | # need to revoke that to test the job. |
543 | @@ -377,6 +395,7 @@ class RemoveArtifactSubscriptionsJobTestCase(TestCaseWithFactory): |
544 | self.assertIn(artifact_indirect_grantee, bug.getDirectSubscribers()) |
545 | self.assertIn(artifact_indirect_grantee, branch.subscribers) |
546 | self.assertIn(artifact_indirect_grantee, gitrepository.subscribers) |
547 | + self.assertIn(artifact_indirect_grantee, snap.subscribers) |
548 | self.assertIn(artifact_indirect_grantee, |
549 | removeSecurityProxy(specification).subscribers) |
550 | |
551 | @@ -389,7 +408,7 @@ class RemoveArtifactSubscriptionsJobTestCase(TestCaseWithFactory): |
552 | return removeSecurityProxy( |
553 | concrete_artifact).getDirectSubscribers() |
554 | |
555 | - def configure_test(bug, branch, gitrepository, specification, |
556 | + def configure_test(bug, branch, gitrepository, snap, specification, |
557 | policy_team_grantee, policy_indirect_grantee, |
558 | artifact_team_grantee, owner): |
559 | concrete_artifact = bug |
560 | @@ -409,7 +428,7 @@ class RemoveArtifactSubscriptionsJobTestCase(TestCaseWithFactory): |
561 | def get_subscribers(concrete_artifact): |
562 | return concrete_artifact.subscribers |
563 | |
564 | - def configure_test(bug, branch, gitrepository, specification, |
565 | + def configure_test(bug, branch, gitrepository, snap, specification, |
566 | policy_team_grantee, policy_indirect_grantee, |
567 | artifact_team_grantee, owner): |
568 | concrete_artifact = branch |
569 | @@ -438,7 +457,7 @@ class RemoveArtifactSubscriptionsJobTestCase(TestCaseWithFactory): |
570 | def get_subscribers(concrete_artifact): |
571 | return concrete_artifact.subscribers |
572 | |
573 | - def configure_test(bug, branch, gitrepository, specification, |
574 | + def configure_test(bug, branch, gitrepository, snap, specification, |
575 | policy_team_grantee, policy_indirect_grantee, |
576 | artifact_team_grantee, owner): |
577 | concrete_artifact = gitrepository |
578 | @@ -459,6 +478,26 @@ class RemoveArtifactSubscriptionsJobTestCase(TestCaseWithFactory): |
579 | self._assert_artifact_change_unsubscribes( |
580 | change_callback, configure_test) |
581 | |
582 | + def _assert_snap_change_unsubscribes(self, change_callback): |
583 | + |
584 | + def get_pillars(concrete_artifact): |
585 | + return [concrete_artifact.project] |
586 | + |
587 | + def get_subscribers(concrete_artifact): |
588 | + return concrete_artifact.subscribers |
589 | + |
590 | + def configure_test(bug, branch, gitrepository, snap, specification, |
591 | + policy_team_grantee, policy_indirect_grantee, |
592 | + artifact_team_grantee, owner): |
593 | + concrete_artifact = snap |
594 | + snap.subscribe(policy_team_grantee, owner) |
595 | + snap.subscribe(policy_indirect_grantee, owner) |
596 | + snap.subscribe(artifact_team_grantee, owner) |
597 | + return concrete_artifact, get_pillars, get_subscribers |
598 | + |
599 | + self._assert_artifact_change_unsubscribes( |
600 | + change_callback, configure_test) |
601 | + |
602 | def _assert_specification_change_unsubscribes(self, change_callback): |
603 | |
604 | def get_pillars(concrete_artifact): |
605 | @@ -467,7 +506,7 @@ class RemoveArtifactSubscriptionsJobTestCase(TestCaseWithFactory): |
606 | def get_subscribers(concrete_artifact): |
607 | return concrete_artifact.subscribers |
608 | |
609 | - def configure_test(bug, branch, gitrepository, specification, |
610 | + def configure_test(bug, branch, gitrepository, snap, specification, |
611 | policy_team_grantee, policy_indirect_grantee, |
612 | artifact_team_grantee, owner): |
613 | naked_spec = removeSecurityProxy(specification) |
614 | @@ -496,6 +535,13 @@ class RemoveArtifactSubscriptionsJobTestCase(TestCaseWithFactory): |
615 | |
616 | self._assert_gitrepository_change_unsubscribes(change_information_type) |
617 | |
618 | + def test_change_information_type_snap(self): |
619 | + def change_information_type(snap): |
620 | + removeSecurityProxy(snap).information_type = ( |
621 | + InformationType.PRIVATESECURITY) |
622 | + |
623 | + self._assert_snap_change_unsubscribes(change_information_type) |
624 | + |
625 | def test_change_information_type_specification(self): |
626 | def change_information_type(specification): |
627 | removeSecurityProxy(specification).information_type = ( |
628 | diff --git a/lib/lp/snappy/interfaces/snap.py b/lib/lp/snappy/interfaces/snap.py |
629 | index 31708c3..71f534b 100644 |
630 | --- a/lib/lp/snappy/interfaces/snap.py |
631 | +++ b/lib/lp/snappy/interfaces/snap.py |
632 | @@ -571,6 +571,10 @@ class ISnapView(Interface): |
633 | # Really ISnapBuild, patched in lp.snappy.interfaces.webservice. |
634 | value_type=Reference(schema=Interface), readonly=True))) |
635 | |
636 | + subscribers = CollectionField( |
637 | + title=_("Persons subscribed to this snap recipe."), |
638 | + readonly=True, value_type=Reference(IPerson)) |
639 | + |
640 | def visibleByUser(user): |
641 | """Can the specified user see this snap recipe?""" |
642 | |
643 | diff --git a/lib/lp/snappy/model/snap.py b/lib/lp/snappy/model/snap.py |
644 | index 141f27a..ba89613 100644 |
645 | --- a/lib/lp/snappy/model/snap.py |
646 | +++ b/lib/lp/snappy/model/snap.py |
647 | @@ -5,6 +5,7 @@ from __future__ import absolute_import, print_function, unicode_literals |
648 | |
649 | __metaclass__ = type |
650 | __all__ = [ |
651 | + 'get_snap_privacy_filter', |
652 | 'Snap', |
653 | ] |
654 | |
655 | @@ -26,6 +27,7 @@ from storm.expr import ( |
656 | And, |
657 | Coalesce, |
658 | Desc, |
659 | + Exists, |
660 | Join, |
661 | LeftJoin, |
662 | Not, |
663 | @@ -71,6 +73,7 @@ from lp.app.errors import ( |
664 | SubscriptionPrivacyViolation, |
665 | UserCannotUnsubscribePerson, |
666 | ) |
667 | +from lp.app.interfaces.launchpad import ILaunchpadCelebrities |
668 | from lp.app.interfaces.security import IAuthorization |
669 | from lp.app.interfaces.services import IService |
670 | from lp.buildmaster.enums import BuildStatus |
671 | @@ -132,6 +135,7 @@ from lp.registry.model.accesspolicy import ( |
672 | reconcile_access_for_artifact, |
673 | ) |
674 | from lp.registry.model.distroseries import DistroSeries |
675 | +from lp.registry.model.person import Person |
676 | from lp.registry.model.series import ACTIVE_STATUSES |
677 | from lp.registry.model.teammembership import TeamParticipation |
678 | from lp.services.config import config |
679 | @@ -1165,6 +1169,13 @@ class Snap(Storm, WebhookTargetMixin): |
680 | person.is_team and |
681 | person.anyone_can_join()) |
682 | |
683 | + @property |
684 | + def subscribers(self): |
685 | + return Store.of(self).find( |
686 | + Person, |
687 | + SnapSubscription.person_id == Person.id, |
688 | + SnapSubscription.snap == self) |
689 | + |
690 | def subscribe(self, person, subscribed_by, ignore_permissions=False): |
691 | """See `ISnap`.""" |
692 | if not self._userCanBeSubscribed(person): |
693 | @@ -1177,9 +1188,12 @@ class Snap(Storm, WebhookTargetMixin): |
694 | person=person, snap=self, subscribed_by=subscribed_by) |
695 | Store.of(subscription).flush() |
696 | service = getUtility(IService, "sharing") |
697 | - service.ensureAccessGrants( |
698 | - [person], subscribed_by, snaps=[self], |
699 | - ignore_permissions=ignore_permissions) |
700 | + _, _, _, snaps, _ = service.getVisibleArtifacts( |
701 | + person, snaps=[self], ignore_permissions=True) |
702 | + if not snaps: |
703 | + service.ensureAccessGrants( |
704 | + [person], subscribed_by, snaps=[self], |
705 | + ignore_permissions=ignore_permissions) |
706 | |
707 | def unsubscribe(self, person, unsubscribed_by, ignore_permissions=False): |
708 | """See `ISnap`.""" |
709 | @@ -1421,9 +1435,12 @@ class SnapSet: |
710 | expressions.append(Snap.owner == owner) |
711 | return IStore(Snap).find(Snap, *expressions) |
712 | |
713 | - def findByIds(self, snap_ids): |
714 | + def findByIds(self, snap_ids, visible_by_user=None): |
715 | """See `ISnapSet`.""" |
716 | - return IStore(ISnap).find(Snap, Snap.id.is_in(snap_ids)) |
717 | + clauses = [Snap.id.is_in(snap_ids)] |
718 | + if visible_by_user is not None: |
719 | + clauses.append(get_snap_privacy_filter(visible_by_user)) |
720 | + return IStore(Snap).find(Snap, *clauses) |
721 | |
722 | def findByOwner(self, owner): |
723 | """See `ISnapSet`.""" |
724 | @@ -1694,9 +1711,11 @@ class SnapStoreSecretsEncryptedContainer(NaClEncryptedContainerBase): |
725 | |
726 | |
727 | def get_snap_privacy_filter(user): |
728 | - """Returns the filter for all private Snaps that the given user is |
729 | - subscribed to (that is, has access without being directly an owner). |
730 | + """Returns the filter for all Snaps that the given user has access to, |
731 | + including private snaps where the user has proper permission. |
732 | |
733 | + :param user: An IPerson, or a class attribute that references an IPerson |
734 | + in the database. |
735 | :return: A storm condition. |
736 | """ |
737 | # XXX pappacena 2021-02-12: Once we do the migration to back fill |
738 | @@ -1707,10 +1726,6 @@ def get_snap_privacy_filter(user): |
739 | if user is None: |
740 | return private_snap == False |
741 | |
742 | - roles = IPersonRoles(user) |
743 | - if roles.in_admin or roles.in_commercial_admin: |
744 | - return True |
745 | - |
746 | artifact_grant_query = Coalesce( |
747 | ArrayIntersects( |
748 | SQL("%s.access_grants" % Snap.__storm_table__), |
749 | @@ -1732,4 +1747,13 @@ def get_snap_privacy_filter(user): |
750 | where=(TeamParticipation.person == user) |
751 | )), False) |
752 | |
753 | - return Or(private_snap == False, artifact_grant_query, policy_grant_query) |
754 | + admin_team_id = getUtility(ILaunchpadCelebrities).admin.id |
755 | + user_is_admin = Exists(Select( |
756 | + TeamParticipation.personID, |
757 | + tables=[TeamParticipation], |
758 | + where=And( |
759 | + TeamParticipation.teamID == admin_team_id, |
760 | + TeamParticipation.person == user))) |
761 | + return Or( |
762 | + private_snap == False, artifact_grant_query, policy_grant_query, |
763 | + user_is_admin) |
764 | diff --git a/lib/lp/snappy/tests/test_snap.py b/lib/lp/snappy/tests/test_snap.py |
765 | index 39362b3..04ed945 100644 |
766 | --- a/lib/lp/snappy/tests/test_snap.py |
767 | +++ b/lib/lp/snappy/tests/test_snap.py |
768 | @@ -3102,8 +3102,7 @@ class TestSnapWebservice(TestCaseWithFactory): |
769 | ws_snaps = [ |
770 | self.webservice.getAbsoluteUrl(api_url(snap)) |
771 | for snap in snaps] |
772 | - commercial_admin = ( |
773 | - getUtility(ILaunchpadCelebrities).commercial_admin.teamowner) |
774 | + admin = getUtility(ILaunchpadCelebrities).admin.teamowner |
775 | logout() |
776 | |
777 | # Anonymous requests can only see public snaps. |
778 | @@ -3141,15 +3140,15 @@ class TestSnapWebservice(TestCaseWithFactory): |
779 | [entry["self_link"] for entry in response.jsonBody()["entries"]]) |
780 | |
781 | # Admins can see all snaps with this URL. |
782 | - commercial_admin_webservice = webservice_for_person( |
783 | - commercial_admin, permission=OAuthPermission.READ_PRIVATE) |
784 | - response = commercial_admin_webservice.named_get( |
785 | + admin_webservice = webservice_for_person( |
786 | + admin, permission=OAuthPermission.READ_PRIVATE) |
787 | + response = admin_webservice.named_get( |
788 | "/+snaps", "findByURL", url=urls[0], api_version="devel") |
789 | self.assertEqual(200, response.status) |
790 | self.assertContentEqual( |
791 | ws_snaps[:4], |
792 | [entry["self_link"] for entry in response.jsonBody()["entries"]]) |
793 | - response = commercial_admin_webservice.named_get( |
794 | + response = admin_webservice.named_get( |
795 | "/+snaps", "findByURL", url=urls[0], owner=person_urls[0], |
796 | api_version="devel") |
797 | self.assertEqual(200, response.status) |
798 | @@ -3180,8 +3179,7 @@ class TestSnapWebservice(TestCaseWithFactory): |
799 | ws_snaps = [ |
800 | self.webservice.getAbsoluteUrl(api_url(snap)) |
801 | for snap in snaps] |
802 | - commercial_admin = ( |
803 | - getUtility(ILaunchpadCelebrities).commercial_admin.teamowner) |
804 | + admin = getUtility(ILaunchpadCelebrities).admin.teamowner |
805 | logout() |
806 | prefix = "https://git.example.org/foo/" |
807 | |
808 | @@ -3222,16 +3220,16 @@ class TestSnapWebservice(TestCaseWithFactory): |
809 | [entry["self_link"] for entry in response.jsonBody()["entries"]]) |
810 | |
811 | # Admins can see all snaps with this URL prefix. |
812 | - commercial_admin_webservice = webservice_for_person( |
813 | - commercial_admin, permission=OAuthPermission.READ_PRIVATE) |
814 | - response = commercial_admin_webservice.named_get( |
815 | + admin_webservice = webservice_for_person( |
816 | + admin, permission=OAuthPermission.READ_PRIVATE) |
817 | + response = admin_webservice.named_get( |
818 | "/+snaps", "findByURLPrefix", url_prefix=prefix, |
819 | api_version="devel") |
820 | self.assertEqual(200, response.status) |
821 | self.assertContentEqual( |
822 | ws_snaps[:8], |
823 | [entry["self_link"] for entry in response.jsonBody()["entries"]]) |
824 | - response = commercial_admin_webservice.named_get( |
825 | + response = admin_webservice.named_get( |
826 | "/+snaps", "findByURLPrefix", url_prefix=prefix, |
827 | owner=person_urls[0], api_version="devel") |
828 | self.assertEqual(200, response.status) |
829 | @@ -3264,8 +3262,7 @@ class TestSnapWebservice(TestCaseWithFactory): |
830 | ws_snaps = [ |
831 | self.webservice.getAbsoluteUrl(api_url(snap)) |
832 | for snap in snaps] |
833 | - commercial_admin = ( |
834 | - getUtility(ILaunchpadCelebrities).commercial_admin.teamowner) |
835 | + admin = getUtility(ILaunchpadCelebrities).admin.teamowner |
836 | logout() |
837 | prefixes = [ |
838 | "https://git.example.org/foo/", "https://git.example.org/bar/"] |
839 | @@ -3307,16 +3304,16 @@ class TestSnapWebservice(TestCaseWithFactory): |
840 | [entry["self_link"] for entry in response.jsonBody()["entries"]]) |
841 | |
842 | # Admins can see all snaps with any of these URL prefixes. |
843 | - commercial_admin_webservice = webservice_for_person( |
844 | - commercial_admin, permission=OAuthPermission.READ_PRIVATE) |
845 | - response = commercial_admin_webservice.named_get( |
846 | + admin_webservice = webservice_for_person( |
847 | + admin, permission=OAuthPermission.READ_PRIVATE) |
848 | + response = admin_webservice.named_get( |
849 | "/+snaps", "findByURLPrefixes", url_prefixes=prefixes, |
850 | api_version="devel") |
851 | self.assertEqual(200, response.status) |
852 | self.assertContentEqual( |
853 | ws_snaps[:16], |
854 | [entry["self_link"] for entry in response.jsonBody()["entries"]]) |
855 | - response = commercial_admin_webservice.named_get( |
856 | + response = admin_webservice.named_get( |
857 | "/+snaps", "findByURLPrefixes", url_prefixes=prefixes, |
858 | owner=person_urls[0], api_version="devel") |
859 | self.assertEqual(200, response.status) |
860 | @@ -3341,8 +3338,7 @@ class TestSnapWebservice(TestCaseWithFactory): |
861 | ws_snaps = [ |
862 | self.webservice.getAbsoluteUrl(api_url(snap)) |
863 | for snap in snaps] |
864 | - commercial_admin = ( |
865 | - getUtility(ILaunchpadCelebrities).commercial_admin.teamowner) |
866 | + admin = getUtility(ILaunchpadCelebrities).admin.teamowner |
867 | logout() |
868 | |
869 | # Anonymous requests can only see public snaps. |
870 | @@ -3382,16 +3378,16 @@ class TestSnapWebservice(TestCaseWithFactory): |
871 | [entry["self_link"] for entry in response.jsonBody()["entries"]]) |
872 | |
873 | # Admins can see all snaps with this store name. |
874 | - commercial_admin_webservice = webservice_for_person( |
875 | - commercial_admin, permission=OAuthPermission.READ_PRIVATE) |
876 | - response = commercial_admin_webservice.named_get( |
877 | + admin_webservice = webservice_for_person( |
878 | + admin, permission=OAuthPermission.READ_PRIVATE) |
879 | + response = admin_webservice.named_get( |
880 | "/+snaps", "findByStoreName", store_name=store_names[0], |
881 | api_version="devel") |
882 | self.assertEqual(200, response.status) |
883 | self.assertContentEqual( |
884 | ws_snaps[:4], |
885 | [entry["self_link"] for entry in response.jsonBody()["entries"]]) |
886 | - response = commercial_admin_webservice.named_get( |
887 | + response = admin_webservice.named_get( |
888 | "/+snaps", "findByStoreName", store_name=store_names[0], |
889 | owner=person_urls[0], api_version="devel") |
890 | self.assertEqual(200, response.status) |
Pushed the requested changes, and added a comment about `get_snap_ privacy_ filter` method.