Merge lp:~adeuring/launchpad/specifications-sharing-service into lp:launchpad
- specifications-sharing-service
- Merge into devel
Status: | Merged |
---|---|
Approved by: | Abel Deuring |
Approved revision: | no longer in the source branch. |
Merged at revision: | 15976 |
Proposed branch: | lp:~adeuring/launchpad/specifications-sharing-service |
Merge into: | lp:launchpad |
Diff against target: |
580 lines (+201/-44) 8 files modified
lib/lp/bugs/model/bug.py (+1/-1) lib/lp/code/browser/branchsubscription.py (+1/-1) lib/lp/code/model/branch.py (+1/-1) lib/lp/code/model/tests/test_branchsubscription.py (+2/-2) lib/lp/registry/browser/pillar.py (+1/-1) lib/lp/registry/interfaces/sharingservice.py (+17/-1) lib/lp/registry/services/sharingservice.py (+76/-8) lib/lp/registry/services/tests/test_sharingservice.py (+102/-29) |
To merge this branch: | bzr merge lp:~adeuring/launchpad/specifications-sharing-service |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Richard Harding (community) | Approve | ||
Review via email: mp+124978@code.launchpad.net |
Commit message
SharingService.
Description of the change
This branch updates several methods of the class SharingService so that
they can deal with specifications in addition to bugs and branches.
changed methods:
getSharedAr
getVisibleA
new method:
getSharedSp
The diff contains some "noise" because some changed methods returned
a tuples (bugs, branches) before this change, and now return a tuple
(bugs, branches, specifications). This requires of course changes in
all callsites.
The method getVisibleArtif
"the right" bugs, and IAllBranches to find "the right" branches; we
do not have yet anything similar for specs, so I iimpkemented the
SQL query for the permission check directly in the class SharingService.
I am a bit concerned about the performance of the SQL query, but
it will for now only be used in a test: my main goal right now is to
make it possible to revoke access grants for specifications, and
I need the changes of getVisibleArtif
SharingService.
test:
./bin/test -vvt lp.registry.
no lint
Preview Diff
1 | === modified file 'lib/lp/bugs/model/bug.py' |
2 | --- lib/lp/bugs/model/bug.py 2012-09-07 20:25:51 +0000 |
3 | +++ lib/lp/bugs/model/bug.py 2012-09-18 16:43:35 +0000 |
4 | @@ -811,7 +811,7 @@ |
5 | # there is at least one bugtask for which access can be checked. |
6 | if self.default_bugtask: |
7 | service = getUtility(IService, 'sharing') |
8 | - bugs, ignored = service.getVisibleArtifacts( |
9 | + bugs, ignored, ignored = service.getVisibleArtifacts( |
10 | person, bugs=[self], ignore_permissions=True) |
11 | if not bugs: |
12 | service.ensureAccessGrants( |
13 | |
14 | === modified file 'lib/lp/code/browser/branchsubscription.py' |
15 | --- lib/lp/code/browser/branchsubscription.py 2012-09-05 21:51:06 +0000 |
16 | +++ lib/lp/code/browser/branchsubscription.py 2012-09-18 16:43:35 +0000 |
17 | @@ -294,7 +294,7 @@ |
18 | url = canonical_url(self.branch) |
19 | # If the subscriber can no longer see the branch, redirect them away. |
20 | service = getUtility(IService, 'sharing') |
21 | - ignored, branches = service.getVisibleArtifacts( |
22 | + ignored, branches, ignored = service.getVisibleArtifacts( |
23 | self.person, branches=[self.branch], ignore_permissions=True) |
24 | if not branches: |
25 | url = canonical_url(self.branch.target) |
26 | |
27 | === modified file 'lib/lp/code/model/branch.py' |
28 | --- lib/lp/code/model/branch.py 2012-09-18 04:13:42 +0000 |
29 | +++ lib/lp/code/model/branch.py 2012-09-18 16:43:35 +0000 |
30 | @@ -896,7 +896,7 @@ |
31 | subscription.review_level = code_review_level |
32 | # Grant the subscriber access if they can't see the branch. |
33 | service = getUtility(IService, 'sharing') |
34 | - ignored, branches = service.getVisibleArtifacts( |
35 | + ignored, branches, ignored = service.getVisibleArtifacts( |
36 | person, branches=[self], ignore_permissions=True) |
37 | if not branches: |
38 | service.ensureAccessGrants( |
39 | |
40 | === modified file 'lib/lp/code/model/tests/test_branchsubscription.py' |
41 | --- lib/lp/code/model/tests/test_branchsubscription.py 2012-07-18 10:44:24 +0000 |
42 | +++ lib/lp/code/model/tests/test_branchsubscription.py 2012-09-18 16:43:35 +0000 |
43 | @@ -133,7 +133,7 @@ |
44 | None, CodeReviewNotificationLevel.NOEMAIL, owner) |
45 | # The stacked on branch should be visible. |
46 | service = getUtility(IService, 'sharing') |
47 | - ignored, visible_branches = service.getVisibleArtifacts( |
48 | + ignored, visible_branches, ignored = service.getVisibleArtifacts( |
49 | grantee, branches=[private_stacked_on_branch]) |
50 | self.assertContentEqual( |
51 | [private_stacked_on_branch], visible_branches) |
52 | @@ -161,7 +161,7 @@ |
53 | grantee, BranchSubscriptionNotificationLevel.NOEMAIL, |
54 | None, CodeReviewNotificationLevel.NOEMAIL, owner) |
55 | # The stacked on branch should not be visible. |
56 | - ignored, visible_branches = service.getVisibleArtifacts( |
57 | + ignored, visible_branches, ignored = service.getVisibleArtifacts( |
58 | grantee, branches=[private_stacked_on_branch]) |
59 | self.assertContentEqual([], visible_branches) |
60 | self.assertIn( |
61 | |
62 | === modified file 'lib/lp/registry/browser/pillar.py' |
63 | --- lib/lp/registry/browser/pillar.py 2012-09-14 01:03:41 +0000 |
64 | +++ lib/lp/registry/browser/pillar.py 2012-09-18 16:43:35 +0000 |
65 | @@ -421,7 +421,7 @@ |
66 | def _loadSharedArtifacts(self): |
67 | # As a concrete can by linked via more than one policy, we use sets to |
68 | # filter out dupes. |
69 | - self.bugtasks, self.branches = ( |
70 | + self.bugtasks, self.branches, self.specifications = ( |
71 | self.sharing_service.getSharedArtifacts( |
72 | self.pillar, self.person, self.user)) |
73 | bug_ids = set([bugtask.bug.id for bugtask in self.bugtasks]) |
74 | |
75 | === modified file 'lib/lp/registry/interfaces/sharingservice.py' |
76 | --- lib/lp/registry/interfaces/sharingservice.py 2012-09-16 12:49:11 +0000 |
77 | +++ lib/lp/registry/interfaces/sharingservice.py 2012-09-18 16:43:35 +0000 |
78 | @@ -28,6 +28,7 @@ |
79 | |
80 | from lp import _ |
81 | from lp.app.interfaces.services import IService |
82 | +from lp.blueprints.interfaces.specification import ISpecification |
83 | from lp.bugs.interfaces.bug import IBug |
84 | from lp.code.interfaces.branch import IBranch |
85 | from lp.registry.enums import ( |
86 | @@ -79,7 +80,7 @@ |
87 | |
88 | :param user: the user making the request. Only artifacts visible to the |
89 | user will be included in the result. |
90 | - :return: a (bugtasks, branches) tuple |
91 | + :return: a (bugtasks, branches, specifications) tuple |
92 | """ |
93 | |
94 | @export_read_operation() |
95 | @@ -116,6 +117,21 @@ |
96 | :return: a collection of branches |
97 | """ |
98 | |
99 | + @export_read_operation() |
100 | + @call_with(user=REQUEST_USER) |
101 | + @operation_parameters( |
102 | + pillar=Reference(IPillar, title=_('Pillar'), required=True), |
103 | + person=Reference(IPerson, title=_('Person'), required=True)) |
104 | + @operation_returns_collection_of(ISpecification) |
105 | + @operation_for_version('devel') |
106 | + def getSharedSpecifications(pillar, person, user): |
107 | + """Return the specifications shared between the pillar and person. |
108 | + |
109 | + :param user: the user making the request. Only branches visible to the |
110 | + user will be included in the result. |
111 | + :return: a collection of specifications. |
112 | + """ |
113 | + |
114 | def getVisibleArtifacts(person, branches=None, bugs=None): |
115 | """Return the artifacts shared with person. |
116 | |
117 | |
118 | === modified file 'lib/lp/registry/services/sharingservice.py' |
119 | --- lib/lp/registry/services/sharingservice.py 2012-09-14 13:25:18 +0000 |
120 | +++ lib/lp/registry/services/sharingservice.py 2012-09-18 16:43:35 +0000 |
121 | @@ -17,15 +17,18 @@ |
122 | Count, |
123 | In, |
124 | Join, |
125 | + LeftJoin, |
126 | Or, |
127 | Select, |
128 | ) |
129 | +from storm.store import Store |
130 | from zope.component import getUtility |
131 | from zope.interface import implements |
132 | from zope.security.interfaces import Unauthorized |
133 | from zope.traversing.browser.absoluteurl import absoluteURL |
134 | |
135 | from lp.app.browser.tales import ObjectImageDisplayAPI |
136 | +from lp.blueprints.model.specification import Specification |
137 | from lp.bugs.interfaces.bugtask import IBugTaskSet |
138 | from lp.bugs.interfaces.bugtasksearch import BugTaskSearchParams |
139 | from lp.code.interfaces.branchcollection import IAllBranches |
140 | @@ -51,13 +54,16 @@ |
141 | ) |
142 | from lp.registry.interfaces.sharingservice import ISharingService |
143 | from lp.registry.model.accesspolicy import ( |
144 | + AccessArtifact, |
145 | AccessArtifactGrant, |
146 | AccessPolicy, |
147 | AccessPolicyArtifact, |
148 | AccessPolicyGrant, |
149 | + AccessPolicyGrantFlat, |
150 | ) |
151 | from lp.registry.model.person import Person |
152 | from lp.registry.model.teammembership import TeamParticipation |
153 | +from lp.services.database.bulk import load |
154 | from lp.services.database.lpstorm import IStore |
155 | from lp.services.database.stormexpr import ColumnSelect |
156 | from lp.services.searchbuilder import any |
157 | @@ -115,17 +121,20 @@ |
158 | |
159 | @available_with_permission('launchpad.Driver', 'pillar') |
160 | def getSharedArtifacts(self, pillar, person, user, include_bugs=True, |
161 | - include_branches=True): |
162 | + include_branches=True, include_specifications=True): |
163 | """See `ISharingService`.""" |
164 | policies = getUtility(IAccessPolicySource).findByPillar([pillar]) |
165 | flat_source = getUtility(IAccessPolicyGrantFlatSource) |
166 | bug_ids = set() |
167 | branch_ids = set() |
168 | + specification_ids = set() |
169 | for artifact in flat_source.findArtifactsByGrantee(person, policies): |
170 | if artifact.bug_id and include_bugs: |
171 | bug_ids.add(artifact.bug_id) |
172 | elif artifact.branch_id and include_branches: |
173 | branch_ids.add(artifact.branch_id) |
174 | + elif artifact.specification_id and include_specifications: |
175 | + specification_ids.add(artifact.specification_id) |
176 | |
177 | # Load the bugs. |
178 | bugtasks = [] |
179 | @@ -140,25 +149,72 @@ |
180 | wanted_branches = all_branches.visibleByUser(user).withIds( |
181 | *branch_ids) |
182 | branches = list(wanted_branches.getBranches()) |
183 | + specifications = [] |
184 | + if specification_ids: |
185 | + specifications = load(Specification, specification_ids) |
186 | |
187 | - return bugtasks, branches |
188 | + return bugtasks, branches, specifications |
189 | |
190 | @available_with_permission('launchpad.Driver', 'pillar') |
191 | def getSharedBugs(self, pillar, person, user): |
192 | """See `ISharingService`.""" |
193 | - bugtasks, ignore = self.getSharedArtifacts( |
194 | - pillar, person, user, include_branches=False) |
195 | + bugtasks, ignore, ignore = self.getSharedArtifacts( |
196 | + pillar, person, user, include_branches=False, |
197 | + include_specifications=False) |
198 | return bugtasks |
199 | |
200 | @available_with_permission('launchpad.Driver', 'pillar') |
201 | def getSharedBranches(self, pillar, person, user): |
202 | """See `ISharingService`.""" |
203 | - ignore, branches = self.getSharedArtifacts( |
204 | - pillar, person, user, include_bugs=False) |
205 | + ignore, branches, ignore = self.getSharedArtifacts( |
206 | + pillar, person, user, include_bugs=False, |
207 | + include_specifications=False) |
208 | return branches |
209 | |
210 | + @available_with_permission('launchpad.Driver', 'pillar') |
211 | + def getSharedSpecifications(self, pillar, person, user): |
212 | + """See `ISharingService`.""" |
213 | + ignore, ignore, specifications = self.getSharedArtifacts( |
214 | + pillar, person, user, include_bugs=False, |
215 | + include_branches=False) |
216 | + return specifications |
217 | + |
218 | + def _getVisiblePrivateSpecificationIDs(self, person, specifications): |
219 | + store = Store.of(specifications[0]) |
220 | + tables = ( |
221 | + Specification, |
222 | + Join( |
223 | + AccessPolicy, |
224 | + And( |
225 | + Or( |
226 | + Specification.distributionID == |
227 | + AccessPolicy.distribution_id, |
228 | + Specification.productID == |
229 | + AccessPolicy.product_id), |
230 | + AccessPolicy.type == Specification.information_type)), |
231 | + Join( |
232 | + AccessPolicyGrantFlat, |
233 | + AccessPolicy.id == AccessPolicyGrantFlat.policy_id |
234 | + ), |
235 | + LeftJoin( |
236 | + AccessArtifact, |
237 | + AccessArtifact.id == |
238 | + AccessPolicyGrantFlat.abstract_artifact_id), |
239 | + Join( |
240 | + TeamParticipation, |
241 | + TeamParticipation.teamID == |
242 | + AccessPolicyGrantFlat.grantee_id)) |
243 | + spec_ids = [spec.id for spec in specifications] |
244 | + return set(store.using(*tables).find( |
245 | + Specification.id, |
246 | + Or( |
247 | + AccessPolicyGrantFlat.abstract_artifact_id == None, |
248 | + AccessArtifact.specification == Specification.id), |
249 | + TeamParticipation.personID == person.id, |
250 | + In(Specification.id, spec_ids))) |
251 | + |
252 | def getVisibleArtifacts(self, person, branches=None, bugs=None, |
253 | - ignore_permissions=False): |
254 | + specifications=None, ignore_permissions=False): |
255 | """See `ISharingService`.""" |
256 | bugs_by_id = {} |
257 | branches_by_id = {} |
258 | @@ -172,6 +228,10 @@ |
259 | and not check_permission('launchpad.View', branch)): |
260 | raise Unauthorized |
261 | branches_by_id[branch.id] = branch |
262 | + for spec in specifications or []: |
263 | + if (not ignore_permissions |
264 | + and not check_permission('launchpad.View', spec)): |
265 | + raise Unauthorized |
266 | |
267 | # Load the bugs. |
268 | visible_bug_ids = [] |
269 | @@ -189,7 +249,15 @@ |
270 | *branches_by_id.keys()) |
271 | visible_branches = list(wanted_branches.getBranches()) |
272 | |
273 | - return visible_bugs, visible_branches |
274 | + visible_specs = [] |
275 | + if specifications: |
276 | + visible_private_spec_ids = self._getVisiblePrivateSpecificationIDs( |
277 | + person, specifications) |
278 | + visible_specs = [ |
279 | + spec for spec in specifications |
280 | + if spec.id in visible_private_spec_ids or not spec.private] |
281 | + |
282 | + return visible_bugs, visible_branches, visible_specs |
283 | |
284 | def getInvisibleArtifacts(self, person, branches=None, bugs=None): |
285 | """See `ISharingService`.""" |
286 | |
287 | === modified file 'lib/lp/registry/services/tests/test_sharingservice.py' |
288 | --- lib/lp/registry/services/tests/test_sharingservice.py 2012-09-16 12:49:11 +0000 |
289 | +++ lib/lp/registry/services/tests/test_sharingservice.py 2012-09-18 16:43:35 +0000 |
290 | @@ -980,8 +980,8 @@ |
291 | |
292 | # Check that grantees have expected access grants and subscriptions. |
293 | for person in [team_grantee, person_grantee]: |
294 | - visible_bugs, visible_branches = self.service.getVisibleArtifacts( |
295 | - person, branches, bugs) |
296 | + visible_bugs, visible_branches, visible_specs = ( |
297 | + self.service.getVisibleArtifacts(person, branches, bugs)) |
298 | self.assertContentEqual(bugs or [], visible_bugs) |
299 | self.assertContentEqual(branches or [], visible_branches) |
300 | for person in [team_grantee, person_grantee]: |
301 | @@ -1004,8 +1004,8 @@ |
302 | for person in [team_grantee, person_grantee]: |
303 | for bug in bugs or []: |
304 | self.assertNotIn(person, bug.getDirectSubscribers()) |
305 | - visible_bugs, visible_branches = self.service.getVisibleArtifacts( |
306 | - person, branches, bugs) |
307 | + visible_bugs, visible_branches, visible_specs = ( |
308 | + self.service.getVisibleArtifacts(person, branches, bugs)) |
309 | self.assertContentEqual([], visible_bugs) |
310 | self.assertContentEqual([], visible_branches) |
311 | |
312 | @@ -1120,8 +1120,8 @@ |
313 | owner = self.factory.makePerson() |
314 | product = self.factory.makeProduct( |
315 | owner=owner, |
316 | - specification_sharing_policy= |
317 | - SpecificationSharingPolicy.PUBLIC_OR_PROPRIETARY) |
318 | + specification_sharing_policy=( |
319 | + SpecificationSharingPolicy.PUBLIC_OR_PROPRIETARY)) |
320 | login_person(owner) |
321 | specification = self.factory.makeSpecification( |
322 | product=product, owner=owner) |
323 | @@ -1232,6 +1232,12 @@ |
324 | product=product, owner=product.owner, |
325 | information_type=InformationType.USERDATA) |
326 | branches.append(branch) |
327 | + specs = [] |
328 | + for x in range(0, 10): |
329 | + spec = self.factory.makeSpecification( |
330 | + product=product, owner=product.owner, |
331 | + information_type=InformationType.PROPRIETARY) |
332 | + specs.append(spec) |
333 | |
334 | # Grant access to grantee as well as the person who will be doing the |
335 | # query. The person who will be doing the query is not granted access |
336 | @@ -1251,32 +1257,39 @@ |
337 | grant_access(bug, i == 9) |
338 | for i, branch in enumerate(branches): |
339 | grant_access(branch, i == 9) |
340 | - return bug_tasks, branches |
341 | + getUtility(IService, 'sharing').ensureAccessGrants( |
342 | + [grantee], product.owner, specifications=specs[:9]) |
343 | + return bug_tasks, branches, specs |
344 | |
345 | def test_getSharedArtifacts(self): |
346 | # Test the getSharedArtifacts method. |
347 | owner = self.factory.makePerson() |
348 | - product = self.factory.makeProduct(owner=owner) |
349 | + product = self.factory.makeProduct( |
350 | + owner=owner, specification_sharing_policy=( |
351 | + SpecificationSharingPolicy.PUBLIC_OR_PROPRIETARY)) |
352 | login_person(owner) |
353 | grantee = self.factory.makePerson() |
354 | user = self.factory.makePerson() |
355 | - bug_tasks, branches = self.create_shared_artifacts( |
356 | + bug_tasks, branches, specs = self.create_shared_artifacts( |
357 | product, grantee, user) |
358 | |
359 | # Check the results. |
360 | - shared_bugtasks, shared_branches = self.service.getSharedArtifacts( |
361 | - product, grantee, user) |
362 | + shared_bugtasks, shared_branches, shared_specs = ( |
363 | + self.service.getSharedArtifacts(product, grantee, user)) |
364 | self.assertContentEqual(bug_tasks[:9], shared_bugtasks) |
365 | self.assertContentEqual(branches[:9], shared_branches) |
366 | + self.assertContentEqual(specs[:9], shared_specs) |
367 | |
368 | def test_getSharedBugs(self): |
369 | # Test the getSharedBugs method. |
370 | owner = self.factory.makePerson() |
371 | - product = self.factory.makeProduct(owner=owner) |
372 | + product = self.factory.makeProduct( |
373 | + owner=owner, specification_sharing_policy=( |
374 | + SpecificationSharingPolicy.PUBLIC_OR_PROPRIETARY)) |
375 | login_person(owner) |
376 | grantee = self.factory.makePerson() |
377 | user = self.factory.makePerson() |
378 | - bug_tasks, ignored = self.create_shared_artifacts( |
379 | + bug_tasks, ignored, ignored = self.create_shared_artifacts( |
380 | product, grantee, user) |
381 | |
382 | # Check the results. |
383 | @@ -1286,11 +1299,13 @@ |
384 | def test_getSharedBranches(self): |
385 | # Test the getSharedBranches method. |
386 | owner = self.factory.makePerson() |
387 | - product = self.factory.makeProduct(owner=owner) |
388 | + product = self.factory.makeProduct( |
389 | + owner=owner, specification_sharing_policy=( |
390 | + SpecificationSharingPolicy.PUBLIC_OR_PROPRIETARY)) |
391 | login_person(owner) |
392 | grantee = self.factory.makePerson() |
393 | user = self.factory.makePerson() |
394 | - ignored, branches = self.create_shared_artifacts( |
395 | + ignored, branches, ignored = self.create_shared_artifacts( |
396 | product, grantee, user) |
397 | |
398 | # Check the results. |
399 | @@ -1298,6 +1313,23 @@ |
400 | product, grantee, user) |
401 | self.assertContentEqual(branches[:9], shared_branches) |
402 | |
403 | + def test_getSharedSpecifications(self): |
404 | + # Test the getSharedSpecifications method. |
405 | + owner = self.factory.makePerson() |
406 | + product = self.factory.makeProduct( |
407 | + owner=owner, specification_sharing_policy=( |
408 | + SpecificationSharingPolicy.PUBLIC_OR_PROPRIETARY)) |
409 | + login_person(owner) |
410 | + grantee = self.factory.makePerson() |
411 | + user = self.factory.makePerson() |
412 | + ignored, ignored, specifications = self.create_shared_artifacts( |
413 | + product, grantee, user) |
414 | + |
415 | + # Check the results. |
416 | + shared_specifications = self.service.getSharedSpecifications( |
417 | + product, grantee, user) |
418 | + self.assertContentEqual(specifications[:9], shared_specifications) |
419 | + |
420 | def test_getPeopleWithAccessBugs(self): |
421 | # Test the getPeopleWithoutAccess method with bugs. |
422 | owner = self.factory.makePerson() |
423 | @@ -1354,7 +1386,10 @@ |
424 | def _make_Artifacts(self): |
425 | # Make artifacts for test (in)visible artifact methods. |
426 | owner = self.factory.makePerson() |
427 | - product = self.factory.makeProduct(owner=owner) |
428 | + product = self.factory.makeProduct( |
429 | + owner=owner, |
430 | + specification_sharing_policy=( |
431 | + SpecificationSharingPolicy.PUBLIC_OR_PROPRIETARY)) |
432 | grantee = self.factory.makePerson() |
433 | login_person(owner) |
434 | |
435 | @@ -1371,6 +1406,13 @@ |
436 | information_type=InformationType.USERDATA) |
437 | branches.append(branch) |
438 | |
439 | + specifications = [] |
440 | + for x in range(0, 10): |
441 | + spec = self.factory.makeSpecification( |
442 | + product=product, owner=owner, |
443 | + information_type=InformationType.PROPRIETARY) |
444 | + specifications.append(spec) |
445 | + |
446 | def grant_access(artifact): |
447 | access_artifact = self.factory.makeAccessArtifact( |
448 | concrete=artifact) |
449 | @@ -1383,20 +1425,33 @@ |
450 | grant_access(bug) |
451 | for branch in branches[:5]: |
452 | grant_access(branch) |
453 | - return grantee, branches, bugs |
454 | + for spec in specifications[:5]: |
455 | + grant_access(spec) |
456 | + return grantee, owner, branches, bugs, specifications |
457 | |
458 | def test_getVisibleArtifacts(self): |
459 | # Test the getVisibleArtifacts method. |
460 | - grantee, branches, bugs = self._make_Artifacts() |
461 | + grantee, ignore, branches, bugs, specs = self._make_Artifacts() |
462 | # Check the results. |
463 | - shared_bugs, shared_branches = self.service.getVisibleArtifacts( |
464 | - grantee, branches, bugs) |
465 | + shared_bugs, shared_branches, shared_specs = ( |
466 | + self.service.getVisibleArtifacts(grantee, branches, bugs, specs)) |
467 | self.assertContentEqual(bugs[:5], shared_bugs) |
468 | self.assertContentEqual(branches[:5], shared_branches) |
469 | + self.assertContentEqual(specs[:5], shared_specs) |
470 | + |
471 | + def test_getVisibleArtifacts_grant_on_pillar(self): |
472 | + # getVisibleArtifacts() returns private specifications if |
473 | + # user has a policy grant for the pillar of the specification. |
474 | + ignore, owner, branches, bugs, specs = self._make_Artifacts() |
475 | + shared_bugs, shared_branches, shared_specs = ( |
476 | + self.service.getVisibleArtifacts(owner, branches, bugs, specs)) |
477 | + self.assertContentEqual(bugs, shared_bugs) |
478 | + self.assertContentEqual(branches, shared_branches) |
479 | + self.assertContentEqual(specs, shared_specs) |
480 | |
481 | def test_getInvisibleArtifacts(self): |
482 | # Test the getInvisibleArtifacts method. |
483 | - grantee, branches, bugs = self._make_Artifacts() |
484 | + grantee, ignore, branches, bugs, specs = self._make_Artifacts() |
485 | # Check the results. |
486 | not_shared_bugs, not_shared_branches = ( |
487 | self.service.getInvisibleArtifacts(grantee, branches, bugs)) |
488 | @@ -1423,16 +1478,16 @@ |
489 | information_type=InformationType.USERDATA) |
490 | bugs.append(bug) |
491 | |
492 | - shared_bugs, shared_branches = self.service.getVisibleArtifacts( |
493 | - grantee, bugs=bugs) |
494 | + shared_bugs, shared_branches, shared_specs = ( |
495 | + self.service.getVisibleArtifacts(grantee, bugs=bugs)) |
496 | self.assertContentEqual(bugs, shared_bugs) |
497 | |
498 | # Change some bugs. |
499 | for x in range(0, 5): |
500 | change_callback(bugs[x], owner) |
501 | # Check the results. |
502 | - shared_bugs, shared_branches = self.service.getVisibleArtifacts( |
503 | - grantee, bugs=bugs) |
504 | + shared_bugs, shared_branches, shared_specs = ( |
505 | + self.service.getVisibleArtifacts(grantee, bugs=bugs)) |
506 | self.assertContentEqual(bugs[5:], shared_bugs) |
507 | |
508 | def test_getVisibleArtifacts_bug_policy_change(self): |
509 | @@ -1519,7 +1574,9 @@ |
510 | def setUp(self): |
511 | super(ApiTestMixin, self).setUp() |
512 | self.owner = self.factory.makePerson(name='thundercat') |
513 | - self.pillar = self.factory.makeProduct(owner=self.owner) |
514 | + self.pillar = self.factory.makeProduct( |
515 | + owner=self.owner, specification_sharing_policy=( |
516 | + SpecificationSharingPolicy.PUBLIC_OR_PROPRIETARY)) |
517 | self.grantee = self.factory.makePerson(name='grantee') |
518 | self.grantor = self.factory.makePerson() |
519 | self.grantee_uri = canonical_url(self.grantee, force_local_path=True) |
520 | @@ -1530,11 +1587,16 @@ |
521 | self.branch = self.factory.makeBranch( |
522 | owner=self.owner, product=self.pillar, |
523 | information_type=InformationType.PRIVATESECURITY) |
524 | + self.spec = self.factory.makeSpecification( |
525 | + product=self.pillar, owner=self.owner, |
526 | + information_type=InformationType.PROPRIETARY) |
527 | login_person(self.owner) |
528 | self.bug.subscribe(self.grantee, self.owner) |
529 | self.branch.subscribe( |
530 | self.grantee, BranchSubscriptionNotificationLevel.NOEMAIL, |
531 | None, CodeReviewNotificationLevel.NOEMAIL, self.owner) |
532 | + getUtility(IService, 'sharing').ensureAccessGrants( |
533 | + [self.grantee], self.grantor, specifications=[self.spec]) |
534 | transaction.commit() |
535 | |
536 | def test_getPillarGranteeData(self): |
537 | @@ -1546,7 +1608,8 @@ |
538 | self.assertEqual( |
539 | {InformationType.USERDATA.name: SharingPermission.ALL.name, |
540 | InformationType.PRIVATESECURITY.name: |
541 | - SharingPermission.SOME.name}, |
542 | + SharingPermission.SOME.name, |
543 | + InformationType.PROPRIETARY.name: SharingPermission.SOME.name}, |
544 | grantee_data['permissions']) |
545 | |
546 | |
547 | @@ -1628,7 +1691,7 @@ |
548 | self.assertEqual(bugtasks[0].title, self.bug.default_bugtask.title) |
549 | |
550 | def test_getSharedBranches(self): |
551 | - # Test the exported getSharedArtifacts() method. |
552 | + # Test the exported getSharedBranches() method. |
553 | ws_pillar = ws_object(self.launchpad, self.pillar) |
554 | ws_grantee = ws_object(self.launchpad, self.grantee) |
555 | branches = self.service.getSharedBranches( |
556 | @@ -1636,13 +1699,23 @@ |
557 | self.assertEqual(1, len(branches)) |
558 | self.assertEqual(branches[0].unique_name, self.branch.unique_name) |
559 | |
560 | + def test_getSharedSpecifications(self): |
561 | + # Test the exported getSharedSpecifications() method. |
562 | + ws_pillar = ws_object(self.launchpad, self.pillar) |
563 | + ws_grantee = ws_object(self.launchpad, self.grantee) |
564 | + specifications = self.service.getSharedSpecifications( |
565 | + pillar=ws_pillar, person=ws_grantee) |
566 | + self.assertEqual(1, len(specifications)) |
567 | + self.assertEqual(specifications[0].name, self.spec.name) |
568 | + |
569 | def test_getSharedArtifacts(self): |
570 | # Test the exported getSharedArtifacts() method. |
571 | ws_pillar = ws_object(self.launchpad, self.pillar) |
572 | ws_grantee = ws_object(self.launchpad, self.grantee) |
573 | - (bugtasks, branches) = self.service.getSharedArtifacts( |
574 | + (bugtasks, branches, specs) = self.service.getSharedArtifacts( |
575 | pillar=ws_pillar, person=ws_grantee) |
576 | self.assertEqual(1, len(bugtasks)) |
577 | self.assertEqual(1, len(branches)) |
578 | + self.assertEqual(1, len(specs)) |
579 | self.assertEqual(bugtasks[0]['title'], self.bug.default_bugtask.title) |
580 | self.assertEqual(branches[0]['unique_name'], self.branch.unique_name) |
Per IRC there's some code aroud #96 and on that reference Branches vs specfications that needs cleaning up.
I also wonder, if we know the query will need to be replaced by some flattened table, if we should have a bug and an XXX on the current query to make can find it easily and come back around to it during out polish work.