Merge lp:~salgado/offspring/make-piston-handlers-privacy-aware into lp:offspring

Proposed by Guilherme Salgado
Status: Superseded
Proposed branch: lp:~salgado/offspring/make-piston-handlers-privacy-aware
Merge into: lp:offspring
Prerequisite: lp:~salgado/offspring/acl-editor
Diff against target: 669 lines (+409/-48)
11 files modified
config/offspring.cfg (+2/-2)
lib/offspring/web/queuemanager/handlers.py (+23/-15)
lib/offspring/web/queuemanager/models.py (+4/-2)
lib/offspring/web/queuemanager/tests/__init__.py (+1/-0)
lib/offspring/web/queuemanager/tests/factory.py (+3/-2)
lib/offspring/web/queuemanager/tests/helpers.py (+14/-0)
lib/offspring/web/queuemanager/tests/test_handlers.py (+300/-0)
lib/offspring/web/queuemanager/tests/test_views.py (+49/-16)
lib/offspring/web/queuemanager/views.py (+13/-5)
lib/offspring/web/settings.py (+0/-3)
lib/offspring/web/settings_production.py (+0/-3)
To merge this branch: bzr merge lp:~salgado/offspring/make-piston-handlers-privacy-aware
Reviewer Review Type Date Requested Status
Offspring Committers Pending
Review via email: mp+84279@code.launchpad.net

Description of the change

Update the piston handlers to include private objects the user is allowed to see.

To post a comment you must log in.
105. By Guilherme Salgado

Plenty of docstrings for tests

106. By Guilherme Salgado

A few changes suggested by Kevin

107. By Guilherme Salgado

merge trunk

108. By Guilherme Salgado

A few more changes suggested by Kevin

109. By Guilherme Salgado

Remove base_dir from config/offspring.cfg or else the tree root will not be used

110. By Guilherme Salgado

Fix one last thing Keving mentioned

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'config/offspring.cfg'
2--- config/offspring.cfg 2011-11-30 14:15:52 +0000
3+++ config/offspring.cfg 2011-12-02 15:32:33 +0000
4@@ -159,8 +159,8 @@
5
6 [publisher]
7 db: postgres://offspring:temp1234@localhost/offspring
8-development_pool: /srv/builds/
9-production_pool: /srv/partners/
10+development_pool: %(base_dir)s/builds/
11+production_pool: %(base_dir)s/partners/
12 signer_directory:
13 signer_files:
14 signer_results:
15
16=== modified file 'lib/offspring/web/queuemanager/handlers.py'
17--- lib/offspring/web/queuemanager/handlers.py 2011-08-13 07:24:06 +0000
18+++ lib/offspring/web/queuemanager/handlers.py 2011-12-02 15:32:33 +0000
19@@ -43,9 +43,11 @@
20 allowed_methods = ('GET')
21
22 def read(self, request, projectName, buildName):
23+ projects = Project.all_objects.accessible_by_user(request.user)
24 try:
25- project = Project.objects.get(pk=projectName)
26- build = BuildResult.objects.get(project=project, name=buildName)
27+ project = projects.get(pk=projectName)
28+ build = BuildResult.all_objects.accessible_by_user(
29+ request.user).get(project=project, name=buildName)
30 except:
31 return rc.NOT_FOUND
32 manifestPath = glob.glob(build.result_directory + '/images/*/*.manifest')[0]
33@@ -56,14 +58,17 @@
34 allowed_methods = ('GET')
35
36 def read(self, request, projectName, buildName):
37+ projects = Project.all_objects.accessible_by_user(request.user)
38+ builds = BuildResult.all_objects.accessible_by_user(request.user)
39 try:
40- project = Project.objects.get(pk=projectName)
41- base_build = BuildResult.objects.get(project=project, name=buildName)
42+ project = projects.get(pk=projectName)
43+ base_build = builds.get(project=project, name=buildName)
44 except:
45 return rc.NOT_FOUND
46 if request.GET.has_key('build'):
47 try:
48- target_build = BuildResult.objects.get(project=project, name=request.GET['build'])
49+ target_build = builds.get(
50+ project=project, name=request.GET['build'])
51 except:
52 return rc.NOT_FOUND
53 else:
54@@ -81,6 +86,7 @@
55 return output
56
57
58+# TODO: Must be made privacy-aware.
59 class ProjectNotificationSubscriptionHandler(BaseHandler):
60 allowed_methods = ('GET', 'POST', 'DELETE')
61 model = ProjectNotificationSubscription
62@@ -138,7 +144,7 @@
63 'reason', 'result', 'notes', 'is_released')
64
65 def read(self, request, projectName=None, buildName=None, builderName=None):
66- results = BuildResult.objects.all()
67+ results = BuildResult.all_objects.accessible_by_user(request.user)
68 if projectName is not None:
69 results = results.filter(project__name=projectName)
70 if buildName is not None:
71@@ -155,10 +161,10 @@
72
73 def read(self, request, projectName=None, request_id=None):
74 try:
75+ requests = BuildRequest.all_objects.accessible_by_user(
76+ request.user)
77 if projectName is not None:
78- requests = BuildRequest.objects.filter(project__name=projectName)
79- else:
80- requests = BuildRequest.objects
81+ requests = requests.filter(project__name=projectName)
82 except:
83 return rc.NOT_FOUND
84 if request_id is not None:
85@@ -170,12 +176,12 @@
86 def delete(self, request, projectName=None, request_id=None):
87 if request.user.has_perm("queuemanager.can_build"):
88 try:
89+ requests = BuildRequest.all_objects.accessible_by_user(
90+ request.user)
91 if projectName is not None:
92- requests = BuildRequest.objects.filter(project__name=projectName)
93- else:
94- requests = BuildRequest.objects
95+ requests = requests.filter(project__name=projectName)
96 except:
97- return RC.NOT_FOUND
98+ return rc.NOT_FOUND
99 if request_id is not None:
100 try:
101 requests.get(pk=request_id).delete()
102@@ -195,7 +201,8 @@
103 def create(self, request, projectName):
104 if request.user.has_perm("queuemanager.can_build"):
105 try:
106- p = Project.objects.get(pk=projectName)
107+ p = Project.all_objects.accessible_by_user(request.user).get(
108+ pk=projectName)
109 if request.POST.has_key('build_reason'):
110 request = BuildRequest.queue_build(p, request.user, reason=request.POST['build_reason'], scoreBonus=25)
111 else:
112@@ -217,8 +224,9 @@
113 'created_at', 'published_at', 'status', 'checklist_url', 'notes')
114
115 def read(self, request, projectName):
116+ objects = Release.all_objects.accessible_by_user(request.user)
117 try:
118- releases = Release.objects.filter(build__project__name=projectName)
119+ releases = objects.filter(build__project__name=projectName)
120 except:
121 return rc.NOT_FOUND
122 return releases
123
124=== modified file 'lib/offspring/web/queuemanager/models.py'
125--- lib/offspring/web/queuemanager/models.py 2011-11-30 14:15:52 +0000
126+++ lib/offspring/web/queuemanager/models.py 2011-12-02 15:32:33 +0000
127@@ -12,7 +12,6 @@
128 )
129 import math
130
131-from django.conf import settings
132 from django.contrib.auth.models import AnonymousUser, User
133 from django.db import (
134 connection,
135@@ -23,9 +22,12 @@
136 AccessGroup,
137 AccessGroupMixin,
138 AccessManager)
139+from offspring.config import get_configuration
140 from offspring.enums import ProjectBuildStates
141
142
143+config = get_configuration()
144+
145 ARCH_CHOICES = (
146 (u'i386', u'i386'),
147 (u'amd64', u'amd64'),
148@@ -412,7 +414,7 @@
149 def result_directory(self):
150 if self.name:
151 try:
152- base_dir = getattr(settings, 'BUILDRESULTS_DIRECTORY', '/srv/builds/')
153+ base_dir = config.get('builder', 'result_dir')
154 buildDate, buildId = self.name.rsplit('-', 1)
155 except:
156 return None
157
158=== modified file 'lib/offspring/web/queuemanager/tests/__init__.py'
159--- lib/offspring/web/queuemanager/tests/__init__.py 2011-12-02 15:32:33 +0000
160+++ lib/offspring/web/queuemanager/tests/__init__.py 2011-12-02 15:32:33 +0000
161@@ -1,2 +1,3 @@
162+from .test_handlers import *
163 from offspring.web.queuemanager.tests.test_models import *
164 from offspring.web.queuemanager.tests.test_views import *
165
166=== modified file 'lib/offspring/web/queuemanager/tests/factory.py'
167--- lib/offspring/web/queuemanager/tests/factory.py 2011-12-02 15:32:33 +0000
168+++ lib/offspring/web/queuemanager/tests/factory.py 2011-12-02 15:32:33 +0000
169@@ -73,7 +73,8 @@
170 title = self.get_unique_string()
171 return ProjectGroup.objects.create(name=name, title=title)
172
173- def make_build_result(self, project=None, name=None, result=None):
174+ def make_build_result(self, project=None, name=None, result=None,
175+ builder=None):
176 """
177 Create a BuildResult with the given project or a newly created one if
178 none is given.
179@@ -83,7 +84,7 @@
180 if project is None:
181 project = self.make_project()
182 return BuildResult.objects.create(
183- project=project, name=name, result=result)
184+ project=project, name=name, result=result, builder=builder)
185
186 def make_release(self, build=None, name=None, creator=None):
187 """
188
189=== added file 'lib/offspring/web/queuemanager/tests/helpers.py'
190--- lib/offspring/web/queuemanager/tests/helpers.py 1970-01-01 00:00:00 +0000
191+++ lib/offspring/web/queuemanager/tests/helpers.py 2011-12-02 15:32:33 +0000
192@@ -0,0 +1,14 @@
193+from django.contrib.auth.models import (
194+ Group,
195+ Permission,
196+ )
197+
198+
199+def grant_permission_to_user(user, permission):
200+ group = Group(name=user.username)
201+ group.save()
202+ group.permissions.add(Permission.objects.get(codename=permission))
203+ group.save()
204+ user.groups.add(group)
205+ user.save()
206+ return user
207
208=== added file 'lib/offspring/web/queuemanager/tests/test_handlers.py'
209--- lib/offspring/web/queuemanager/tests/test_handlers.py 1970-01-01 00:00:00 +0000
210+++ lib/offspring/web/queuemanager/tests/test_handlers.py 2011-12-02 15:32:33 +0000
211@@ -0,0 +1,300 @@
212+import errno
213+import os
214+
215+from django.contrib.auth import authenticate, login
216+from django.http import HttpRequest, HttpResponse
217+from django.test import TestCase
218+from django.contrib.sessions.middleware import SessionMiddleware
219+
220+from piston.utils import rc
221+
222+from offspring.web.queuemanager.models import BuildRequest
223+from offspring.web.queuemanager.handlers import (
224+ BuildManifestComparisonHandler,
225+ BuildManifestHandler,
226+ BuildRequestHandler,
227+ BuildResultHandler,
228+ ReleaseHandler,
229+ )
230+from offspring.web.queuemanager.tests.factory import factory
231+from offspring.web.queuemanager.tests.helpers import grant_permission_to_user
232+
233+
234+class BaseHandlerTestCase(TestCase):
235+
236+ def setUp(self):
237+ super(BaseHandlerTestCase, self).setUp()
238+ self.request = HttpRequest()
239+ self.request.method = 'GET'
240+ # Set request.user and process the request manually using
241+ # SessionMiddleware so that we can use login(request, user) in tests.
242+ self.request.user = None
243+ SessionMiddleware().process_request(self.request)
244+
245+ def _login(self, user):
246+ user = authenticate(username=user.username, password=user.username)
247+ login(self.request, user)
248+ return user
249+
250+
251+class BuildResultHandlerTests(BaseHandlerTestCase):
252+
253+ def test_builds_for_inexistent_project(self):
254+ results = BuildResultHandler().read(
255+ self.request, projectName='not-existent')
256+ self.assertEqual(0, results.count())
257+
258+ def test_inexistent_build(self):
259+ results = BuildResultHandler().read(
260+ self.request, buildName='not-existent')
261+ self.assertEqual(0, results.count())
262+
263+ def test_public_project_builds(self):
264+ # The builds of public projects are visible to anyone.
265+ build = make_build(is_private=False)
266+ self.assertBuildIsVisibleToUser(build, factory.make_user())
267+
268+ def test_private_project_build_is_visible_to_project_owner(self):
269+ build = make_build(is_private=True)
270+ self.assertBuildIsVisibleToUser(build, build.project.owner)
271+
272+ def test_private_project_builds_invisible_to_user(self):
273+ # If the user has no rights to see a given project, they'll get an
274+ # empty list of builds, just like if the project didn't exist.
275+ build = make_build(is_private=True)
276+ self.assertBuildIsNotVisibleToUser(build, factory.make_user())
277+
278+ def assertBuildIsVisibleToUser(self, build, user):
279+ """Assert that the given build is visible to the given user."""
280+ user = self._login(user)
281+ handler = BuildResultHandler()
282+
283+ # It is visible when looking at all project builds...
284+ results = handler.read(self.request, projectName=build.project.name)
285+ self.assertEqual(1, results.count())
286+ self.assertEqual([build], list(results))
287+
288+ # when looking at one specific build ...
289+ results = handler.read(self.request, buildName=build.name)
290+ self.assertEqual(1, results.count())
291+ self.assertEqual([build], list(results))
292+
293+ # and when looking at all builds of a builder.
294+ results = handler.read(self.request, builderName=build.builder.name)
295+ self.assertEqual(1, results.count())
296+ self.assertEqual([build], list(results))
297+
298+ def assertBuildIsNotVisibleToUser(self, build, user):
299+ """Assert that the given build is not visible to the given user."""
300+ user = self._login(user)
301+ handler = BuildResultHandler()
302+
303+ # It is *not* visible when looking at all project builds...
304+ results = handler.read(self.request, projectName=build.project.name)
305+ self.assertEqual(0, results.count())
306+
307+ # when looking at one specific build ...
308+ results = handler.read(self.request, buildName=build.name)
309+ self.assertEqual(0, results.count())
310+
311+ # and when looking at all builds of a builder.
312+ results = handler.read(self.request, builderName=build.builder.name)
313+ self.assertEqual(0, results.count())
314+
315+
316+class BuildRequestHandlerTests(BaseHandlerTestCase):
317+
318+ def test_public_build_request_is_visible_to_anyone(self):
319+ job = factory.make_build_request(
320+ project=factory.make_project(is_private=False))
321+ results = BuildRequestHandler().read(
322+ self.request, projectName=job.project.name, request_id=job.id)
323+ self.assertEqual(job, results)
324+
325+ def test_private_build_request_is_visible_to_owner(self):
326+ job = factory.make_build_request(
327+ project=factory.make_project(is_private=True))
328+ self._login(job.project.owner)
329+ results = BuildRequestHandler().read(
330+ self.request, projectName=job.project.name, request_id=job.id)
331+ self.assertEqual(job, results)
332+
333+ def test_private_build_request_is_not_visible_to_others(self):
334+ job = factory.make_build_request(
335+ project=factory.make_project(is_private=True))
336+ self._login(factory.make_user())
337+ self.assertRaises(
338+ BuildRequest.DoesNotExist,
339+ BuildRequestHandler().read,
340+ self.request, projectName=job.project.name, request_id=job.id)
341+
342+ def test_new_build_request_on_public_project(self):
343+ project = factory.make_project(is_private=False)
344+ self.assertCreateReturnCode(
345+ project, factory.make_user(), rc.CREATED.status_code)
346+
347+ def test_owner_requests_new_build_on_private_project(self):
348+ project = factory.make_project(is_private=True)
349+ self.assertCreateReturnCode(
350+ project, project.owner, rc.CREATED.status_code)
351+
352+ def test_other_user_requests_new_build_on_private_project(self):
353+ project = factory.make_project(is_private=True)
354+ self.assertCreateReturnCode(
355+ project, factory.make_user(), rc.BAD_REQUEST.status_code)
356+
357+ def test_delete_build_request_on_public_project(self):
358+ job = factory.make_build_request(
359+ project=factory.make_project(is_private=False))
360+ self.assertDeleteReturnCode(
361+ job, factory.make_user(), rc.DELETED.status_code)
362+
363+ def test_owner_deletes_build_request_on_private_project(self):
364+ job = factory.make_build_request(
365+ project=factory.make_project(is_private=True))
366+ self.assertDeleteReturnCode(
367+ job, job.project.owner, rc.DELETED.status_code)
368+
369+ def test_other_user_deletes_build_request_on_private_project(self):
370+ job = factory.make_build_request(
371+ project=factory.make_project(is_private=True))
372+ self.assertDeleteReturnCode(
373+ job, factory.make_user(), rc.NOT_FOUND.status_code)
374+
375+ def assertCreateReturnCode(self, project, user, return_code):
376+ """Assert that BuildRequestHandler.create() returns the given code.
377+
378+ Also grant the given user the 'can_build' permission and logs it in.
379+ """
380+ grant_permission_to_user(user, 'can_build')
381+ self._login(user)
382+ result = BuildRequestHandler().create(
383+ self.request, projectName=project.name)
384+ self.assertEqual(return_code, result.status_code)
385+
386+ def assertDeleteReturnCode(self, job, user, return_code):
387+ """Assert that BuildRequestHandler.delete() returns the given code.
388+
389+ Also grant the given user the 'can_build' permission and logs it in.
390+ """
391+ grant_permission_to_user(user, 'can_build')
392+ self._login(user)
393+ result = BuildRequestHandler().delete(
394+ self.request, projectName=job.project.name, request_id=job.id)
395+ self.assertEqual(return_code, result.status_code)
396+
397+
398+class ReleaseHandlerTests(BaseHandlerTestCase):
399+
400+ def test_public_project_release(self):
401+ release = factory.make_release(make_build(is_private=False))
402+ results = ReleaseHandler().read(
403+ self.request, projectName=release.build.project.name)
404+ self.assertEqual(1, results.count())
405+ self.assertEqual([release], list(results))
406+
407+ def test_private_project_release_is_visible_to_owner(self):
408+ release = factory.make_release(make_build(is_private=True))
409+ user = self._login(release.build.project.owner)
410+ results = ReleaseHandler().read(
411+ self.request, projectName=release.build.project.name)
412+ self.assertEqual(1, results.count())
413+ self.assertEqual([release], list(results))
414+
415+ def test_private_project_release_is_not_visible_to_others(self):
416+ release = factory.make_release(make_build(is_private=True))
417+ user = self._login(factory.make_user())
418+ results = ReleaseHandler().read(
419+ self.request, projectName=release.build.project.name)
420+ self.assertEqual(0, results.count())
421+
422+
423+class BuildManifestHandlerTests(BaseHandlerTestCase):
424+
425+ def test_public_project_build_manifest(self):
426+ build = make_build(is_private=False)
427+ make_build_manifest_file(build)
428+ results = BuildManifestHandler().read(
429+ self.request, build.project.name, build.name)
430+ self.assertEqual([{'package': 'foo', 'version': '1.2'}], results)
431+
432+ def test_private_project_build_manifest_is_visible_to_owner(self):
433+ build = make_build(is_private=True)
434+ make_build_manifest_file(build)
435+ user = self._login(build.project.owner)
436+ results = BuildManifestHandler().read(
437+ self.request, build.project.name, build.name)
438+ self.assertEqual([{'package': 'foo', 'version': '1.2'}], results)
439+
440+ def test_private_project_build_manifest_returns_404_for_others(self):
441+ build = make_build(is_private=True)
442+ make_build_manifest_file(build)
443+ user = self._login(factory.make_user())
444+ results = BuildManifestHandler().read(
445+ self.request, build.project.name, build.name)
446+ self.assertTrue(isinstance(results, HttpResponse))
447+ self.assertEqual(404, results.status_code)
448+
449+
450+class BuildManifestComparisonHandlerTests(BaseHandlerTestCase):
451+
452+ def test_public_projects_build_manifest_comparison(self):
453+ build = make_build(is_private=False)
454+ build2 = factory.make_build_result(
455+ project=build.project, builder=factory.make_lexbuilder())
456+ make_build_manifest_file(build)
457+ make_build_manifest_file(build2)
458+ self.request.GET['build'] = build2.name
459+ results = BuildManifestComparisonHandler().read(
460+ self.request, build.project.name, build.name)
461+ self.assertEqual(
462+ [{'changeType': 'no_change', 'target_version': '1.2',
463+ 'base_version': '1.2', 'package': 'foo'}],
464+ results)
465+
466+ def test_private_build_manifest_comparison_is_visible_to_owner(self):
467+ build = make_build(is_private=True)
468+ build2 = factory.make_build_result(
469+ project=build.project, builder=factory.make_lexbuilder())
470+ make_build_manifest_file(build)
471+ make_build_manifest_file(build2)
472+ user = self._login(build.project.owner)
473+ self.request.GET['build'] = build2.name
474+ results = BuildManifestComparisonHandler().read(
475+ self.request, build.project.name, build.name)
476+ self.assertEqual(
477+ [{'changeType': 'no_change', 'target_version': '1.2',
478+ 'base_version': '1.2', 'package': 'foo'}],
479+ results)
480+
481+ def test_private_build_manifest_comparison_returns_404_for_others(self):
482+ build = make_build(is_private=True)
483+ build2 = factory.make_build_result(
484+ project=build.project, builder=factory.make_lexbuilder())
485+ make_build_manifest_file(build)
486+ make_build_manifest_file(build2)
487+ user = self._login(factory.make_user())
488+ self.request.GET['build'] = build2.name
489+ results = BuildManifestComparisonHandler().read(
490+ self.request, build.project.name, build.name)
491+ self.assertTrue(isinstance(results, HttpResponse))
492+ self.assertEqual(404, results.status_code)
493+
494+
495+def make_build(is_private):
496+ return factory.make_build_result(
497+ project=factory.make_project(is_private=is_private),
498+ builder=factory.make_lexbuilder())
499+
500+
501+def make_build_manifest_file(build):
502+ """Create a manifest file where BuildManifestHandler expects to find it."""
503+ manifest_dir = os.path.join(build.result_directory, 'images', 'build')
504+ try:
505+ os.makedirs(manifest_dir)
506+ except OSError, exc:
507+ if exc.errno != errno.EEXIST:
508+ raise
509+ path = os.path.join(manifest_dir, 'build.manifest')
510+ with open(path, 'w') as fd:
511+ fd.write('foo 1.2')
512
513=== modified file 'lib/offspring/web/queuemanager/tests/test_views.py'
514--- lib/offspring/web/queuemanager/tests/test_views.py 2011-12-02 15:32:33 +0000
515+++ lib/offspring/web/queuemanager/tests/test_views.py 2011-12-02 15:32:33 +0000
516@@ -1,9 +1,5 @@
517 from django.core.urlresolvers import reverse
518-from django.contrib.auth.models import (
519- AnonymousUser,
520- Group,
521- Permission,
522- )
523+from django.contrib.auth.models import AnonymousUser
524 from django.http import Http404
525 from django.test import TestCase
526
527@@ -13,6 +9,7 @@
528 )
529 from offspring.web.queuemanager.views import get_possibly_private_object
530 from offspring.web.queuemanager.tests.factory import factory
531+from offspring.web.queuemanager.tests.helpers import grant_permission_to_user
532
533
534 class Test_get_possibly_private_object(TestCase):
535@@ -259,17 +256,53 @@
536 self.assertEqual([], list(access_group.members.all()))
537
538
539+class ProjectBuildsViewTests(TestCase, ProjectViewTestsMixin):
540+ view_path = 'offspring.web.queuemanager.views.builds'
541+
542+ def get_expected_page_heading(self, project):
543+ return 'Build Records for %s' % project.title
544+
545+ def test_public_project(self):
546+ project = factory.make_project(is_private=False)
547+ build = factory.make_build_result(project=project)
548+ response = self.client.get(
549+ reverse(self.view_path, args=[project.name]))
550+ self.assertContains(
551+ response, self.get_expected_page_heading(project),
552+ status_code=200, msg_prefix=response.content)
553+
554+
555+class OverallBuildsViewTests(TestCase):
556+ view_path = 'offspring.web.queuemanager.views.builds'
557+
558+ def test_public_builds_are_shown(self):
559+ project = factory.make_project(is_private=False)
560+ build = factory.make_build_result(project=project)
561+ response = self.client.get(reverse(self.view_path))
562+ self.assertContains(
563+ response, build.name, status_code=200, msg_prefix=response.content)
564+
565+ def test_private_builds_are_shown_if_user_has_rights(self):
566+ project = factory.make_project(is_private=True)
567+ build = factory.make_build_result(project=project)
568+ user = project.owner
569+ self.assertTrue(
570+ self.client.login(username=user.username, password=user.username))
571+ response = self.client.get(reverse(self.view_path))
572+ self.assertContains(
573+ response, build.name, status_code=200, msg_prefix=response.content)
574+
575+ def test_private_builds_are_not_shown_if_user_has_no_rights(self):
576+ project = factory.make_project(is_private=True)
577+ build = factory.make_build_result(project=project)
578+ user = factory.make_user()
579+ self.assertTrue(
580+ self.client.login(username=user.username, password=user.username))
581+ response = self.client.get(reverse(self.view_path))
582+ self.assertNotContains(
583+ response, build.name, status_code=200, msg_prefix=response.content)
584+
585+
586 def make_user_and_login(client):
587 user = factory.make_user()
588 return client.login(username=user.username, password=user.username)
589-
590-
591-def grant_permission_to_user(user, permission):
592- group = Group(name=user.username)
593- group.save()
594- group.permissions.add(Permission.objects.get(codename=permission))
595- group.save()
596- user.groups.add(group)
597- user.save()
598- return user
599-
600
601=== modified file 'lib/offspring/web/queuemanager/views.py'
602--- lib/offspring/web/queuemanager/views.py 2011-12-02 15:32:33 +0000
603+++ lib/offspring/web/queuemanager/views.py 2011-12-02 15:32:33 +0000
604@@ -107,13 +107,15 @@
605 context_instance=RequestContext(request))
606
607 def builds(request, projectName=None):
608+ user = request.user
609+ user_visible_builds = BuildResult.all_objects.accessible_by_user(user)
610 if projectName is not None:
611- p = get_object_or_404(Project, pk=projectName)
612- buildResults_list = BuildResult.objects.filter(
613- project = projectName).order_by("finished_at").reverse()
614+ p = get_possibly_private_object(user, Project, pk=projectName)
615+ buildResults_list = user_visible_builds.filter(
616+ project=projectName).order_by("finished_at").reverse()
617 else:
618 p = None
619- buildResults_list = BuildResult.objects.select_related(
620+ buildResults_list = user_visible_builds.select_related(
621 'builder', 'requestor', 'project').order_by("finished_at").reverse()
622 paginator = Paginator(buildResults_list, 15)
623
624@@ -127,8 +129,12 @@
625 except (EmptyPage, InvalidPage):
626 buildResults = paginator.page(paginator.num_pages)
627
628+ is_private = False
629+ if p is not None and p.is_private:
630+ is_private = True
631 pageData = {
632 'project' : p,
633+ 'is_private' : is_private,
634 'build_results' : buildResults,
635 'pillar' : 'builds'
636 }
637@@ -232,7 +238,9 @@
638 request.user)
639 p = get_possibly_private_object(
640 request.user, user_visible_objects, pk=projectName)
641- project_build_results = BuildResult.objects.filter(
642+ user_visible_builds = BuildResult.all_objects.accessible_by_user(
643+ request.user)
644+ project_build_results = user_visible_builds.filter(
645 project = p).exclude(result = None)
646 build_stats = {
647 'fail_count' : project_build_results.filter(result = ProjectBuildStates.FAILED).count(),
648
649=== modified file 'lib/offspring/web/settings.py'
650--- lib/offspring/web/settings.py 2011-11-18 15:45:06 +0000
651+++ lib/offspring/web/settings.py 2011-12-02 15:32:33 +0000
652@@ -131,6 +131,3 @@
653 CELERY_RESULT_BACKEND = 'djcelery.backends.database.DatabaseBackend'
654 CELERYBEAT_SCHEDULER = 'djcelery.schedulers.DatabaseScheduler'
655 djcelery.setup_loader()
656-
657-# Path to build results
658-BUILDRESULTS_DIRECTORY = '/srv/builds/'
659
660=== modified file 'lib/offspring/web/settings_production.py'
661--- lib/offspring/web/settings_production.py 2011-11-30 14:15:52 +0000
662+++ lib/offspring/web/settings_production.py 2011-12-02 15:32:33 +0000
663@@ -16,6 +16,3 @@
664 EMAIL_HOST = 'localhost'
665
666 MEDIA_URL = 'https://offspring.com/assets/'
667-
668-# Path to build results
669-BUILDRESULTS_DIRECTORY = '/srv/offspring.com/www/builds/'

Subscribers

People subscribed via source and target branches