Merge lp:~salgado/offspring/make-piston-handlers-privacy-aware into lp:~linaro-automation/offspring/private-builds

Proposed by Guilherme Salgado
Status: Merged
Approved by: James Tunnicliffe
Approved revision: no longer in the source branch.
Merged at revision: 61
Proposed branch: lp:~salgado/offspring/make-piston-handlers-privacy-aware
Merge into: lp:~linaro-automation/offspring/private-builds
Diff against target: 322 lines (+233/-9)
4 files modified
lib/offspring/web/queuemanager/handlers.py (+15/-7)
lib/offspring/web/queuemanager/tests/__init__.py (+1/-0)
lib/offspring/web/queuemanager/tests/factory.py (+4/-2)
lib/offspring/web/queuemanager/tests/test_handlers.py (+213/-0)
To merge this branch: bzr merge lp:~salgado/offspring/make-piston-handlers-privacy-aware
Reviewer Review Type Date Requested Status
James Tunnicliffe (community) Approve
Review via email: mp+79350@code.launchpad.net

Description of the change

Update most of the piston handlers to include private objects the user is allowed to see. There are two handlers that still need to be updated but those will be done in another branch as this one is already of a reasonable size.

To post a comment you must log in.
Revision history for this message
James Tunnicliffe (dooferlad) wrote :

Good stuff.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/offspring/web/queuemanager/handlers.py'
--- lib/offspring/web/queuemanager/handlers.py 2011-08-13 07:24:06 +0000
+++ lib/offspring/web/queuemanager/handlers.py 2011-10-13 23:27:26 +0000
@@ -43,9 +43,11 @@
43 allowed_methods = ('GET')43 allowed_methods = ('GET')
4444
45 def read(self, request, projectName, buildName):45 def read(self, request, projectName, buildName):
46 projects = Project.all_objects.accessible_by_user(request.user)
46 try:47 try:
47 project = Project.objects.get(pk=projectName)48 project = projects.get(pk=projectName)
48 build = BuildResult.objects.get(project=project, name=buildName)49 build = BuildResult.all_objects.accessible_by_user(
50 request.user).get(project=project, name=buildName)
49 except: 51 except:
50 return rc.NOT_FOUND52 return rc.NOT_FOUND
51 manifestPath = glob.glob(build.result_directory + '/images/*/*.manifest')[0]53 manifestPath = glob.glob(build.result_directory + '/images/*/*.manifest')[0]
@@ -56,14 +58,17 @@
56 allowed_methods = ('GET')58 allowed_methods = ('GET')
5759
58 def read(self, request, projectName, buildName):60 def read(self, request, projectName, buildName):
61 projects = Project.all_objects.accessible_by_user(request.user)
62 builds = BuildResult.all_objects.accessible_by_user(request.user)
59 try:63 try:
60 project = Project.objects.get(pk=projectName)64 project = projects.get(pk=projectName)
61 base_build = BuildResult.objects.get(project=project, name=buildName)65 base_build = builds.get(project=project, name=buildName)
62 except:66 except:
63 return rc.NOT_FOUND67 return rc.NOT_FOUND
64 if request.GET.has_key('build'):68 if request.GET.has_key('build'):
65 try:69 try:
66 target_build = BuildResult.objects.get(project=project, name=request.GET['build'])70 target_build = builds.get(
71 project=project, name=request.GET['build'])
67 except:72 except:
68 return rc.NOT_FOUND73 return rc.NOT_FOUND
69 else:74 else:
@@ -81,6 +86,7 @@
81 return output86 return output
8287
8388
89# TODO: Must be made privacy-aware.
84class ProjectNotificationSubscriptionHandler(BaseHandler):90class ProjectNotificationSubscriptionHandler(BaseHandler):
85 allowed_methods = ('GET', 'POST', 'DELETE')91 allowed_methods = ('GET', 'POST', 'DELETE')
86 model = ProjectNotificationSubscription92 model = ProjectNotificationSubscription
@@ -138,7 +144,7 @@
138 'reason', 'result', 'notes', 'is_released')144 'reason', 'result', 'notes', 'is_released')
139145
140 def read(self, request, projectName=None, buildName=None, builderName=None):146 def read(self, request, projectName=None, buildName=None, builderName=None):
141 results = BuildResult.objects.all()147 results = BuildResult.all_objects.accessible_by_user(request.user)
142 if projectName is not None:148 if projectName is not None:
143 results = results.filter(project__name=projectName)149 results = results.filter(project__name=projectName)
144 if buildName is not None:150 if buildName is not None:
@@ -148,6 +154,7 @@
148 return results154 return results
149155
150156
157# TODO: Must be made privacy-aware.
151class BuildRequestHandler(BaseHandler):158class BuildRequestHandler(BaseHandler):
152 allowed_methods = ('GET', 'POST', 'DELETE')159 allowed_methods = ('GET', 'POST', 'DELETE')
153 model = BuildRequest160 model = BuildRequest
@@ -217,8 +224,9 @@
217 'created_at', 'published_at', 'status', 'checklist_url', 'notes')224 'created_at', 'published_at', 'status', 'checklist_url', 'notes')
218225
219 def read(self, request, projectName):226 def read(self, request, projectName):
227 objects = Release.all_objects.accessible_by_user(request.user)
220 try:228 try:
221 releases = Release.objects.filter(build__project__name=projectName)229 releases = objects.filter(build__project__name=projectName)
222 except:230 except:
223 return rc.NOT_FOUND231 return rc.NOT_FOUND
224 return releases232 return releases
225233
=== modified file 'lib/offspring/web/queuemanager/tests/__init__.py'
--- lib/offspring/web/queuemanager/tests/__init__.py 2011-09-29 19:19:09 +0000
+++ lib/offspring/web/queuemanager/tests/__init__.py 2011-10-13 23:27:26 +0000
@@ -1,2 +1,3 @@
1from .test_handlers import *
1from .test_models import *2from .test_models import *
2from .test_views import *3from .test_views import *
34
=== modified file 'lib/offspring/web/queuemanager/tests/factory.py'
--- lib/offspring/web/queuemanager/tests/factory.py 2011-10-10 14:11:38 +0000
+++ lib/offspring/web/queuemanager/tests/factory.py 2011-10-13 23:27:26 +0000
@@ -66,13 +66,15 @@
66 group.save()66 group.save()
67 return group67 return group
6868
69 def makeBuildResult(self, project=None, name=None, result=None):69 def makeBuildResult(self, project=None, name=None, result=None,
70 builder=None):
70 if name is None:71 if name is None:
71 name = self.getUniqueString()72 name = self.getUniqueString()
72 if project is None:73 if project is None:
73 project = self.makeProject()74 project = self.makeProject()
74 project.save()75 project.save()
75 result = BuildResult(name=name, project=project, result=result)76 result = BuildResult(name=name, project=project, result=result,
77 builder=builder)
76 result.save()78 result.save()
77 return result79 return result
7880
7981
=== added file 'lib/offspring/web/queuemanager/tests/test_handlers.py'
--- lib/offspring/web/queuemanager/tests/test_handlers.py 1970-01-01 00:00:00 +0000
+++ lib/offspring/web/queuemanager/tests/test_handlers.py 2011-10-13 23:27:26 +0000
@@ -0,0 +1,213 @@
1import errno
2import os
3
4from django.contrib.auth import authenticate, login
5from django.http import HttpRequest, HttpResponse
6from django.test import TestCase
7from django.contrib.sessions.middleware import SessionMiddleware
8
9from offspring.web.queuemanager.handlers import (
10 BuildManifestComparisonHandler,
11 BuildManifestHandler,
12 BuildResultHandler,
13 ReleaseHandler,
14 )
15from offspring.web.queuemanager.tests.factory import factory
16
17
18class BaseHandlerTestCase(TestCase):
19
20 def setUp(self):
21 super(BaseHandlerTestCase, self).setUp()
22 self.request = HttpRequest()
23 self.request.method = 'GET'
24 # Set request.user and process the request manually using
25 # SessionMiddleware so that we can use login(request, user) in tests.
26 self.request.user = None
27 SessionMiddleware().process_request(self.request)
28
29 def _login(self, user):
30 user = authenticate(username=user.username, password=user.username)
31 login(self.request, user)
32 return user
33
34
35class BuildResultHandlerTests(BaseHandlerTestCase):
36
37 def test_builds_for_inexistent_project(self):
38 results = BuildResultHandler().read(
39 self.request, projectName='not-existent')
40 self.assertEqual(0, results.count())
41
42 def test_inexistent_build(self):
43 results = BuildResultHandler().read(
44 self.request, buildName='not-existent')
45 self.assertEqual(0, results.count())
46
47 def test_public_project_builds(self):
48 # The builds of public projects are visible to anyone.
49 build = make_build(is_private=False)
50 self.assertBuildIsVisibleToUser(build, factory.makeUser())
51
52 def test_private_project_build_is_visible_to_project_owner(self):
53 build = make_build(is_private=True)
54 self.assertBuildIsVisibleToUser(build, build.project.owner)
55
56 def test_private_project_builds_invisible_to_user(self):
57 # If the user has no rights to see a given project, they'll get an
58 # empty list of builds, just like if the project didn't exist.
59 build = make_build(is_private=True)
60 self.assertBuildIsNotVisibleToUser(build, factory.makeUser())
61
62 def assertBuildIsVisibleToUser(self, build, user):
63 """Assert that the given build is visible to the given user."""
64 user = self._login(user)
65 handler = BuildResultHandler()
66
67 # It is visible when looking at all project builds...
68 results = handler.read(self.request, projectName=build.project.name)
69 self.assertEqual(1, results.count())
70 self.assertEqual([build], list(results))
71
72 # when looking at one specific build ...
73 results = handler.read(self.request, buildName=build.name)
74 self.assertEqual(1, results.count())
75 self.assertEqual([build], list(results))
76
77 # and when looking at all builds of a builder.
78 results = handler.read(self.request, builderName=build.builder.name)
79 self.assertEqual(1, results.count())
80 self.assertEqual([build], list(results))
81
82 def assertBuildIsNotVisibleToUser(self, build, user):
83 """Assert that the given build is not visible to the given user."""
84 user = self._login(user)
85 handler = BuildResultHandler()
86
87 # It is *not* visible when looking at all project builds...
88 results = handler.read(self.request, projectName=build.project.name)
89 self.assertEqual(0, results.count())
90
91 # when looking at one specific build ...
92 results = handler.read(self.request, buildName=build.name)
93 self.assertEqual(0, results.count())
94
95 # and when looking at all builds of a builder.
96 results = handler.read(self.request, builderName=build.builder.name)
97 self.assertEqual(0, results.count())
98
99
100class ReleaseHandlerTests(BaseHandlerTestCase):
101
102 def test_public_project_release(self):
103 release = factory.makeRelease(make_build(is_private=False))
104 results = ReleaseHandler().read(
105 self.request, projectName=release.build.project.name)
106 self.assertEqual(1, results.count())
107 self.assertEqual([release], list(results))
108
109 def test_private_project_release_is_visible_to_owner(self):
110 release = factory.makeRelease(make_build(is_private=True))
111 user = self._login(release.build.project.owner)
112 results = ReleaseHandler().read(
113 self.request, projectName=release.build.project.name)
114 self.assertEqual(1, results.count())
115 self.assertEqual([release], list(results))
116
117 def test_private_project_release_is_not_visible_to_others(self):
118 release = factory.makeRelease(make_build(is_private=True))
119 user = self._login(factory.makeUser())
120 results = ReleaseHandler().read(
121 self.request, projectName=release.build.project.name)
122 self.assertEqual(0, results.count())
123
124
125class BuildManifestHandlerTests(BaseHandlerTestCase):
126
127 def test_public_project_build_manifest(self):
128 build = make_build(is_private=False)
129 make_build_manifest_file(build)
130 results = BuildManifestHandler().read(
131 self.request, build.project.name, build.name)
132 self.assertEqual([{'package': 'foo', 'version': '1.2'}], results)
133
134 def test_private_project_build_manifest_is_visible_to_owner(self):
135 build = make_build(is_private=True)
136 make_build_manifest_file(build)
137 user = self._login(build.project.owner)
138 results = BuildManifestHandler().read(
139 self.request, build.project.name, build.name)
140 self.assertEqual([{'package': 'foo', 'version': '1.2'}], results)
141
142 def test_private_project_build_manifest_returns_404_for_others(self):
143 build = make_build(is_private=True)
144 make_build_manifest_file(build)
145 user = self._login(factory.makeUser())
146 results = BuildManifestHandler().read(
147 self.request, build.project.name, build.name)
148 self.assertTrue(isinstance(results, HttpResponse))
149 self.assertEqual(404, results.status_code)
150
151
152class BuildManifestComparisonHandlerTests(BaseHandlerTestCase):
153
154 def test_public_projects_build_manifest_comparison(self):
155 build = make_build(is_private=False)
156 build2 = factory.makeBuildResult(
157 project=build.project, builder=factory.makeLexbuilder())
158 make_build_manifest_file(build)
159 make_build_manifest_file(build2)
160 self.request.GET['build'] = build2.name
161 results = BuildManifestComparisonHandler().read(
162 self.request, build.project.name, build.name)
163 self.assertEqual(
164 [{'changeType': 'no_change', 'target_version': '1.2',
165 'base_version': '1.2', 'package': 'foo'}],
166 results)
167
168 def test_private_build_manifest_comparison_is_visible_to_owner(self):
169 build = make_build(is_private=True)
170 build2 = factory.makeBuildResult(
171 project=build.project, builder=factory.makeLexbuilder())
172 make_build_manifest_file(build)
173 make_build_manifest_file(build2)
174 user = self._login(build.project.owner)
175 self.request.GET['build'] = build2.name
176 results = BuildManifestComparisonHandler().read(
177 self.request, build.project.name, build.name)
178 self.assertEqual(
179 [{'changeType': 'no_change', 'target_version': '1.2',
180 'base_version': '1.2', 'package': 'foo'}],
181 results)
182
183 def test_private_build_manifest_comparison_returns_404_for_others(self):
184 build = make_build(is_private=True)
185 build2 = factory.makeBuildResult(
186 project=build.project, builder=factory.makeLexbuilder())
187 make_build_manifest_file(build)
188 make_build_manifest_file(build2)
189 user = self._login(factory.makeUser())
190 self.request.GET['build'] = build2.name
191 results = BuildManifestComparisonHandler().read(
192 self.request, build.project.name, build.name)
193 self.assertTrue(isinstance(results, HttpResponse))
194 self.assertEqual(404, results.status_code)
195
196
197def make_build(is_private):
198 return factory.makeBuildResult(
199 project=factory.makeProject(is_private=is_private),
200 builder=factory.makeLexbuilder())
201
202
203def make_build_manifest_file(build):
204 """Create a manifest file where BuildManifestHandler expects to find it."""
205 manifest_dir = os.path.join(build.result_directory, 'images', 'build')
206 try:
207 os.makedirs(manifest_dir)
208 except OSError, exc:
209 if exc.errno != errno.EEXIST:
210 raise
211 path = os.path.join(manifest_dir, 'build.manifest')
212 with open(path, 'w') as fd:
213 fd.write('foo 1.2')

Subscribers

People subscribed via source and target branches