Merge lp:~salgado/offspring/disable-subscription-for-private-projects into lp:~linaro-automation/offspring/private-builds

Proposed by Guilherme Salgado
Status: Superseded
Proposed branch: lp:~salgado/offspring/disable-subscription-for-private-projects
Merge into: lp:~linaro-automation/offspring/private-builds
Diff against target: 338 lines (+164/-26)
8 files modified
lib/offspring/master/models.py (+1/-0)
lib/offspring/master/notifications.py (+3/-0)
lib/offspring/master/tests.py (+39/-0)
lib/offspring/web/queuemanager/handlers.py (+9/-9)
lib/offspring/web/queuemanager/tests/helpers.py (+14/-0)
lib/offspring/web/queuemanager/tests/test_handlers.py (+87/-0)
lib/offspring/web/queuemanager/tests/test_views.py (+2/-16)
lib/offspring/web/templates/queuemanager/project_details.html (+9/-1)
To merge this branch: bzr merge lp:~salgado/offspring/disable-subscription-for-private-projects
Reviewer Review Type Date Requested Status
Linaro Infrastructure Pending
Review via email: mp+79604@code.launchpad.net

Description of the change

This branch disables the ability to subscribe to notifications of private projects as well as the sending of notifications about private projects

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

Remove 4 unused methods (one from Project and 3 from ProjectGroup)

87. By Cody A.W. Somerville

Deprecate shell script configuration file offspring-builder.config for builder component and build archiver script - instead store that configuration in offspring.cfg and have offspring-builder-config script that will output shell environment variables to be set by components of Offspring still written in shell. Kudos to Michael Hudson and Guilherme Salgado from Linaro. N.B. Project build configuration in build configuration branches are still written in shell.

88. By Guilherme Salgado

Add the hwpack wrapper used by Linaro

89. By Guilherme Salgado

Add an anonymous object factory for queuemanager tests

90. By Guilherme Salgado

Add support for private objects to web.queuemanger, with a custom API for querying only the objects a given user is allowed to see and helper methods to check if a given object is visible to a given user

91. By Kevin McDermott

Merge database-testing [r=salgado] [f=891557]

This adds a test infrastructure for the "master" part of offspring, including
setting up the database tables needed and support for fixtures.

In addition, there new tests added for the master code, and the notifications
that are sent.

Also, the configuration mechanism has been replaced by a simple ConfigParser
implementation.

92. By Kevin McDermott

Merge add-path-independence [r=salgado] [f=897203]

This changes the default file used in Offspring, to use a file sourced from the
root of the offspring Python source files.

The path to the configuration file can still be explicitly set either through
the environment or explicitly on the command-line.

93. By Kevin McDermott

Merge slave-testing [r=jedimike] [f=898118]

This adds tests for the Offspring LexBuilderSlave functionality.

94. By Kevin McDermott

Merge fix-base-dir-in-config [r=salgado] [f=899220]

This fixes get_configuration() to only overwrite the base_dir in the
configuration object returned in the event that there's no base_dir already
set.

95. By Kevin McDermott

Merge slave-testing-server [r=salgado] [f=898118]

This adds tests for the LexbuilderSlaveServer.

96. By Kevin McDermott

Add coverage make targets for slave and master.

97. By Kevin McDermott

Missed config gets.

98. By Guilherme Salgado

Make project and build views return a 404 if the user is not allowed to see that private project/build

99. By Kevin McDermott

Merge passing-ssh-key-to-slave2 [r=bigkevmcd] [a=jamestunnicliff]

This adds support for passing an SSH key to the slave builder, to use when
checking out configurations.

100. By Kevin McDermott

Add test-web-coverage as a target.

101. By Guilherme Salgado

Add a new page (+acl) to edit the list of people who can see a given private project.

102. By Kevin McDermott

Don't import tests otherwise they run twice.

103. By Kevin McDermott

Merge error-in-queuemanager-views [r=salgado] [f=900337]

This adds tests for the LaunchpadProject form, and removes an error in the view
code for creating LaunchpadProjects.

104. By Guilherme Salgado

Change the builds() view to show private builds if the user is allowed to see them.

105. By Guilherme Salgado

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

106. By Kevin McDermott

Merge add-queue-metrics [r=cody,schwuk] [f=902183]

This adds the core queue-metrics logic, calculating the average build time
either for a Project, or for all Projects, over a configurable period of time.

It also adds a new management command build_metrics which outputs some basic
metrics.

107. By Cody A.W. Somerville

Updated archive-builds script to include hwpacks generated by linaro-media-create in artifacts that are pruned (LP #819371).

108. By Kevin McDermott

Merge slave-testing-integration [r=Cody] [f=898118]

This adds test coverage for offspring.slave.slave.

109. By Guilherme Salgado

Update list views to include private objects the user is allowed to see or
redact information about the ones the user is not allowed to see.

The project list view hides the projects the user is not allowed to see
whereas the builder list redacts information about current builds when it's
for a project the user is not allowed to see

110. By Guilherme Salgado

Update the builder_details view to omit details of the current job if the user
has no rights to see it.

Also shows a small padlock icon next to private projects on both the list of
projects and the list of builds

111. By Kevin McDermott

Merge add-queue-wait-time [r=salgado] [f=902183]

This implements queue wait time metric to the gathered metrics.

112. By Kevin McDermott

Merge non-scheduled-builds [r=salgado] [f=902183]

This adds support for non-scheduled (automated) builds to the metrics
determination.

113. By Guilherme Salgado

Update the build failures sidebar to skip private builds the user is not allowed to see, and the queued-builds and build-farm sidebars to simply state it's a private build (without any other information) when the user is not allowed to see them

114. By Guilherme Salgado

Make sure Lexbuilders with no current_job are considered public

115. By Guilherme Salgado

Make sure we can't have a private project without an owner, as that could render them completely inaccessible

116. By Guilherme Salgado

Disable subscriptions and notifications to private projects by not showing the Subscribe link for private projects and refraining from sending any notification for builds of private projects.

117. By Guilherme Salgado

merge trunk

Unmerged revisions

117. By Guilherme Salgado

merge trunk

116. By Guilherme Salgado

Disable subscriptions and notifications to private projects by not showing the Subscribe link for private projects and refraining from sending any notification for builds of private projects.

115. By Guilherme Salgado

Make sure we can't have a private project without an owner, as that could render them completely inaccessible

114. By Guilherme Salgado

Make sure Lexbuilders with no current_job are considered public

113. By Guilherme Salgado

Update the build failures sidebar to skip private builds the user is not allowed to see, and the queued-builds and build-farm sidebars to simply state it's a private build (without any other information) when the user is not allowed to see them

112. By Kevin McDermott

Merge non-scheduled-builds [r=salgado] [f=902183]

This adds support for non-scheduled (automated) builds to the metrics
determination.

111. By Kevin McDermott

Merge add-queue-wait-time [r=salgado] [f=902183]

This implements queue wait time metric to the gathered metrics.

110. By Guilherme Salgado

Update the builder_details view to omit details of the current job if the user
has no rights to see it.

Also shows a small padlock icon next to private projects on both the list of
projects and the list of builds

109. By Guilherme Salgado

Update list views to include private objects the user is allowed to see or
redact information about the ones the user is not allowed to see.

The project list view hides the projects the user is not allowed to see
whereas the builder list redacts information about current builds when it's
for a project the user is not allowed to see

108. By Kevin McDermott

Merge slave-testing-integration [r=Cody] [f=898118]

This adds test coverage for offspring.slave.slave.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/offspring/master/models.py'
2--- lib/offspring/master/models.py 2011-09-23 14:01:26 +0000
3+++ lib/offspring/master/models.py 2011-10-17 19:26:36 +0000
4@@ -157,6 +157,7 @@
5 title = Unicode()
6 priority = Int(default=0)
7 is_active = Bool(default=True)
8+ is_private = Bool(default=False)
9 launchpad_project_id = Unicode()
10 launchpad_project = Reference(launchpad_project_id, "LaunchpadProject.name")
11 suite = Unicode()
12
13=== modified file 'lib/offspring/master/notifications.py'
14--- lib/offspring/master/notifications.py 2010-11-29 08:27:24 +0000
15+++ lib/offspring/master/notifications.py 2011-10-17 19:26:36 +0000
16@@ -88,6 +88,9 @@
17 def notify_buildresult(build_result):
18 project = build_result.project
19 builder = build_result.builder
20+ if project.is_private:
21+ # We don't support subscriptions for private projects.
22+ return
23
24 build_date, build_id = build_result.name.rsplit('-', 1)
25 build_url = "%s/%s/%s/%s" % (offspring.config.web('build_results_uri'), project.name, build_date, build_id)
26
27=== modified file 'lib/offspring/master/tests.py'
28--- lib/offspring/master/tests.py 2011-09-08 19:12:29 +0000
29+++ lib/offspring/master/tests.py 2011-10-17 19:26:36 +0000
30@@ -5,7 +5,12 @@
31 import unittest
32
33 from offspring import config
34+from offspring.master.models import (
35+ Project,
36+ ProjectNotificationSubscription,
37+ )
38 from offspring.master.notifications import (
39+ notify_buildresult,
40 notify_crash,
41 notify_problem,
42 )
43@@ -20,6 +25,12 @@
44 self.mails.append((sender, rcpt, msg))
45
46
47+class FakeLexBuilder(object):
48+
49+ def __init__(self, name):
50+ self.name = name
51+
52+
53 class Factory(object):
54
55 def __init__(self):
56@@ -29,6 +40,13 @@
57 self.counter += 1
58 return 'str%s' % self.counter
59
60+ def makeProject(self, is_private=False):
61+ name = self.getUniqueString()
62+ project = Project(name=name)
63+ project.title = name.decode('utf-8')
64+ project.is_private = is_private
65+ return project
66+
67
68 class TestCaseWithFactory(unittest.TestCase):
69
70@@ -119,3 +137,24 @@
71 from_header = mailer.mails[0][0]
72 sender_real_name, sender_addr = email.utils.parseaddr(from_header)
73 self.assertEqual(addr, sender_addr)
74+
75+
76+class FakeBuildResult(object):
77+
78+ def __init__(self, project):
79+ self.project = project
80+ self.builder = None
81+
82+
83+class TestNotifyBuildResult(TestCaseWithFactory):
84+
85+ def test_private_project(self):
86+ # For simplicity, we don't support subscriptions for private projects,
87+ # so no notifications are sent here even though there is a project
88+ # subscription.
89+ mailer = StubMailer()
90+ project = self.factory.makeProject(is_private=True)
91+ project.subscriptions = [ProjectNotificationSubscription()]
92+ build = FakeBuildResult(project)
93+ notify_buildresult(build)
94+ self.assertEquals([], mailer.mails)
95
96=== modified file 'lib/offspring/web/queuemanager/handlers.py'
97--- lib/offspring/web/queuemanager/handlers.py 2011-10-13 23:23:41 +0000
98+++ lib/offspring/web/queuemanager/handlers.py 2011-10-17 19:26:36 +0000
99@@ -154,7 +154,6 @@
100 return results
101
102
103-# TODO: Must be made privacy-aware.
104 class BuildRequestHandler(BaseHandler):
105 allowed_methods = ('GET', 'POST', 'DELETE')
106 model = BuildRequest
107@@ -162,10 +161,10 @@
108
109 def read(self, request, projectName=None, request_id=None):
110 try:
111+ requests = BuildRequest.all_objects.accessible_by_user(
112+ request.user)
113 if projectName is not None:
114- requests = BuildRequest.objects.filter(project__name=projectName)
115- else:
116- requests = BuildRequest.objects
117+ requests = requests.filter(project__name=projectName)
118 except:
119 return rc.NOT_FOUND
120 if request_id is not None:
121@@ -177,12 +176,12 @@
122 def delete(self, request, projectName=None, request_id=None):
123 if request.user.has_perm("queuemanager.can_build"):
124 try:
125+ requests = BuildRequest.all_objects.accessible_by_user(
126+ request.user)
127 if projectName is not None:
128- requests = BuildRequest.objects.filter(project__name=projectName)
129- else:
130- requests = BuildRequest.objects
131+ requests = requests.filter(project__name=projectName)
132 except:
133- return RC.NOT_FOUND
134+ return rc.NOT_FOUND
135 if request_id is not None:
136 try:
137 requests.get(pk=request_id).delete()
138@@ -202,7 +201,8 @@
139 def create(self, request, projectName):
140 if request.user.has_perm("queuemanager.can_build"):
141 try:
142- p = Project.objects.get(pk=projectName)
143+ p = Project.all_objects.accessible_by_user(request.user).get(
144+ pk=projectName)
145 if request.POST.has_key('build_reason'):
146 request = BuildRequest.queue_build(p, request.user, reason=request.POST['build_reason'], scoreBonus=25)
147 else:
148
149=== added file 'lib/offspring/web/queuemanager/tests/helpers.py'
150--- lib/offspring/web/queuemanager/tests/helpers.py 1970-01-01 00:00:00 +0000
151+++ lib/offspring/web/queuemanager/tests/helpers.py 2011-10-17 19:26:36 +0000
152@@ -0,0 +1,14 @@
153+from django.contrib.auth.models import (
154+ Group,
155+ Permission,
156+ )
157+
158+
159+def grant_permission_to_user(user, permission):
160+ group = Group(name=user.username)
161+ group.save()
162+ group.permissions.add(Permission.objects.get(codename=permission))
163+ group.save()
164+ user.groups.add(group)
165+ user.save()
166+ return user
167
168=== modified file 'lib/offspring/web/queuemanager/tests/test_handlers.py'
169--- lib/offspring/web/queuemanager/tests/test_handlers.py 2011-10-13 23:16:02 +0000
170+++ lib/offspring/web/queuemanager/tests/test_handlers.py 2011-10-17 19:26:36 +0000
171@@ -6,13 +6,18 @@
172 from django.test import TestCase
173 from django.contrib.sessions.middleware import SessionMiddleware
174
175+from piston.utils import rc
176+
177+from offspring.web.queuemanager.models import BuildRequest
178 from offspring.web.queuemanager.handlers import (
179 BuildManifestComparisonHandler,
180 BuildManifestHandler,
181+ BuildRequestHandler,
182 BuildResultHandler,
183 ReleaseHandler,
184 )
185 from offspring.web.queuemanager.tests.factory import factory
186+from offspring.web.queuemanager.tests.helpers import grant_permission_to_user
187
188
189 class BaseHandlerTestCase(TestCase):
190@@ -97,6 +102,88 @@
191 self.assertEqual(0, results.count())
192
193
194+class BuildRequestHandlerTests(BaseHandlerTestCase):
195+
196+ def test_public_build_request_is_visible_to_anyone(self):
197+ job = factory.makeBuildRequest(
198+ project=factory.makeProject(is_private=False))
199+ results = BuildRequestHandler().read(
200+ self.request, projectName=job.project.name, request_id=job.id)
201+ self.assertEqual(job, results)
202+
203+ def test_private_build_request_is_visible_to_owner(self):
204+ job = factory.makeBuildRequest(
205+ project=factory.makeProject(is_private=True))
206+ self._login(job.project.owner)
207+ results = BuildRequestHandler().read(
208+ self.request, projectName=job.project.name, request_id=job.id)
209+ self.assertEqual(job, results)
210+
211+ def test_private_build_request_is_not_visible_to_others(self):
212+ job = factory.makeBuildRequest(
213+ project=factory.makeProject(is_private=True))
214+ self._login(factory.makeUser())
215+ self.assertRaises(
216+ BuildRequest.DoesNotExist,
217+ BuildRequestHandler().read,
218+ self.request, projectName=job.project.name, request_id=job.id)
219+
220+ def test_new_build_request_on_public_project(self):
221+ project = factory.makeProject(is_private=False)
222+ self.assertCreateReturnCode(
223+ project, factory.makeUser(), rc.CREATED.status_code)
224+
225+ def test_owner_requests_new_build_on_private_project(self):
226+ project = factory.makeProject(is_private=True)
227+ self.assertCreateReturnCode(
228+ project, project.owner, rc.CREATED.status_code)
229+
230+ def test_other_user_requests_new_build_on_private_project(self):
231+ project = factory.makeProject(is_private=True)
232+ self.assertCreateReturnCode(
233+ project, factory.makeUser(), rc.BAD_REQUEST.status_code)
234+
235+ def test_delete_build_request_on_public_project(self):
236+ job = factory.makeBuildRequest(
237+ project=factory.makeProject(is_private=False))
238+ self.assertDeleteReturnCode(
239+ job, factory.makeUser(), rc.DELETED.status_code)
240+
241+ def test_owner_deletes_build_request_on_private_project(self):
242+ job = factory.makeBuildRequest(
243+ project=factory.makeProject(is_private=True))
244+ self.assertDeleteReturnCode(
245+ job, job.project.owner, rc.DELETED.status_code)
246+
247+ def test_other_user_deletes_build_request_on_private_project(self):
248+ job = factory.makeBuildRequest(
249+ project=factory.makeProject(is_private=True))
250+ self.assertDeleteReturnCode(
251+ job, factory.makeUser(), rc.NOT_FOUND.status_code)
252+
253+ def assertCreateReturnCode(self, project, user, return_code):
254+ """Assert that BuildRequestHandler.create() returns the given code.
255+
256+ Also grant the given user the 'can_build' permission and logs it in.
257+ """
258+ grant_permission_to_user(user, 'can_build')
259+ self._login(user)
260+ result = BuildRequestHandler().create(
261+ self.request, projectName=project.name)
262+ self.assertEqual(return_code, result.status_code)
263+
264+ def assertDeleteReturnCode(self, job, user, return_code):
265+ """Assert that BuildRequestHandler.delete() returns the given code.
266+
267+ Also grant the given user the 'can_build' permission and logs it in.
268+ """
269+ grant_permission_to_user(user, 'can_build')
270+ self._login(user)
271+ result = BuildRequestHandler().delete(
272+ self.request, projectName=job.project.name, request_id=job.id)
273+ self.assertEqual(return_code, result.status_code)
274+
275+
276 class ReleaseHandlerTests(BaseHandlerTestCase):
277
278 def test_public_project_release(self):
279
280=== modified file 'lib/offspring/web/queuemanager/tests/test_views.py'
281--- lib/offspring/web/queuemanager/tests/test_views.py 2011-10-10 21:15:48 +0000
282+++ lib/offspring/web/queuemanager/tests/test_views.py 2011-10-17 19:26:36 +0000
283@@ -1,9 +1,5 @@
284 from django.core.urlresolvers import reverse
285-from django.contrib.auth.models import (
286- AnonymousUser,
287- Group,
288- Permission,
289- )
290+from django.contrib.auth.models import AnonymousUser
291 from django.http import Http404
292 from django.test import TestCase
293
294@@ -13,6 +9,7 @@
295 )
296 from offspring.web.queuemanager.views import get_possibly_private_object
297 from offspring.web.queuemanager.tests.factory import factory
298+from offspring.web.queuemanager.tests.helpers import grant_permission_to_user
299
300
301 class Test_get_possibly_private_object(TestCase):
302@@ -309,14 +306,3 @@
303 def make_user_and_login(client):
304 user = factory.makeUser()
305 return client.login(username=user.username, password=user.username)
306-
307-
308-def grant_permission_to_user(user, permission):
309- group = Group(name=user.username)
310- group.save()
311- group.permissions.add(Permission.objects.get(codename=permission))
312- group.save()
313- user.groups.add(group)
314- user.save()
315- return user
316-
317
318=== modified file 'lib/offspring/web/templates/queuemanager/project_details.html'
319--- lib/offspring/web/templates/queuemanager/project_details.html 2011-10-10 19:42:14 +0000
320+++ lib/offspring/web/templates/queuemanager/project_details.html 2011-10-17 19:26:36 +0000
321@@ -537,8 +537,16 @@
322 contents:"${isSubscribed ? 'Unsubscribe' : 'Subscribe'} to Notifications",
323 dynamicContents:true,
324 icon: "/assets/images/mail--plus.png",
325+{% if not user.is_authenticated %}
326+ prompt: "You must login to manage your project build notification subscription",
327+ disabled: true,
328+{% else %} {% if project.is_private %}
329+ prompt: "Build notification subscription disabled for private projects",
330+ disabled: true,
331+{% else %}
332 prompt: "Manage project build notification subscription",
333- disabled: {% if user.is_authenticated %}false{% else %}true{% endif %},
334+ disabled: false,
335+{% endif %} {% endif %}
336 click: function() {
337 toggle_subscription();
338 return false;

Subscribers

People subscribed via source and target branches