Merge lp:~stevenk/launchpad/no-edit-import-for-you-redux into lp:launchpad

Proposed by Steve Kowalik on 2012-10-02
Status: Merged
Approved by: Steve Kowalik on 2012-10-02
Approved revision: no longer in the source branch.
Merged at revision: 16072
Proposed branch: lp:~stevenk/launchpad/no-edit-import-for-you-redux
Merge into: lp:launchpad
Diff against target: 210 lines (+32/-34)
5 files modified
lib/lp/code/browser/branch.py (+2/-6)
lib/lp/code/browser/codeimport.py (+13/-13)
lib/lp/code/browser/tests/test_codeimport.py (+16/-2)
lib/lp/code/model/branch.py (+0/-2)
lib/lp/code/model/codeimport.py (+1/-11)
To merge this branch: bzr merge lp:~stevenk/launchpad/no-edit-import-for-you-redux
Reviewer Review Type Date Requested Status
Ian Booth (community) 2012-10-02 Approve on 2012-10-02
Review via email: mp+127613@code.launchpad.net

Commit Message

Raise Unauthorized if the user isn't an admin or in vcs imports on IBranch:+edit-import.

Description of the Change

https://code.launchpad.net/~stevenk/launchpad/no-edit-import-for-you/+merge/127417 was landed yesterday, but was rolled back due to the test failing on buildbot. This branch contains the same fix with a new test.

To post a comment you must log in.
Ian Booth (wallyworld) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/code/browser/branch.py'
2--- lib/lp/code/browser/branch.py 2012-10-02 07:45:15 +0000
3+++ lib/lp/code/browser/branch.py 2012-10-02 23:35:24 +0000
4@@ -381,18 +381,14 @@
5
6 def edit_import(self):
7 text = 'Edit import source or review import'
8- enabled = True
9 enabled = (
10 self.context.branch_type == BranchType.IMPORTED and
11 check_permission('launchpad.Edit', self.context.code_import))
12- return Link(
13- '+edit-import', text, icon='edit', enabled=enabled)
14+ return Link('+edit-import', text, icon='edit', enabled=enabled)
15
16 @enabled_with_permission('launchpad.Edit')
17 def upgrade_branch(self):
18- enabled = False
19- if self.context.needs_upgrading:
20- enabled = True
21+ enabled = self.context.needs_upgrading
22 return Link(
23 '+upgrade', 'Upgrade this branch', icon='edit', enabled=enabled)
24
25
26=== modified file 'lib/lp/code/browser/codeimport.py'
27--- lib/lp/code/browser/codeimport.py 2012-10-02 07:45:15 +0000
28+++ lib/lp/code/browser/codeimport.py 2012-10-02 23:35:24 +0000
29@@ -1,4 +1,4 @@
30-# Copyright 2009-2011 Canonical Ltd. This software is licensed under the
31+# Copyright 2009-2012 Canonical Ltd. This software is licensed under the
32 # GNU Affero General Public License version 3 (see the file LICENSE).
33
34 """Browser views for CodeImports."""
35@@ -27,6 +27,7 @@
36 from zope.formlib import form
37 from zope.interface import Interface
38 from zope.schema import Choice
39+from zope.security.interfaces import Unauthorized
40
41 from lp import _
42 from lp.app.browser.launchpadform import (
43@@ -35,7 +36,6 @@
44 LaunchpadFormView,
45 )
46 from lp.app.errors import NotFoundError
47-from lp.app.interfaces.launchpad import ILaunchpadCelebrities
48 from lp.app.widgets.itemswidgets import (
49 LaunchpadDropdownWidget,
50 LaunchpadRadioWidget,
51@@ -67,6 +67,7 @@
52 )
53 from lp.code.interfaces.codeimportmachine import ICodeImportMachineSet
54 from lp.registry.interfaces.product import IProduct
55+from lp.registry.interfaces.role import IPersonRoles
56 from lp.services.fields import URIField
57 from lp.services.propertycache import cachedproperty
58 from lp.services.webapp import (
59@@ -155,9 +156,8 @@
60 @cachedproperty
61 def _super_user(self):
62 """Is the user an admin or member of vcs-imports?"""
63- celebs = getUtility(ILaunchpadCelebrities)
64- return (self.user.inTeam(celebs.admin) or
65- self.user.inTeam(celebs.vcs_imports))
66+ role = IPersonRoles(self.user)
67+ return role.in_admin or role.in_vcs_imports
68
69 def showOptionalMarker(self, field_name):
70 """Don't show the optional marker for rcs locations."""
71@@ -217,9 +217,7 @@
72 """The fields presented on the form for editing a code import."""
73
74 use_template(IBranch, ['owner'])
75- use_template(
76- ICodeImport,
77- ['rcs_type', 'cvs_root', 'cvs_module'])
78+ use_template(ICodeImport, ['rcs_type', 'cvs_root', 'cvs_module'])
79
80 svn_branch_url = URIField(
81 title=_("Branch URL"), required=False,
82@@ -306,10 +304,10 @@
83
84 @property
85 def label(self):
86+ label = 'Request a code import'
87 if self.context_is_product:
88- return 'Request a code import for %s' % self.context.displayname
89- else:
90- return 'Request a code import'
91+ label += ' for %s' % self.context.displayname
92+ return label
93
94 @property
95 def cancel_url(self):
96@@ -338,7 +336,7 @@
97 self.form_fields = any_owner_field + self.form_fields
98
99 def setUpWidgets(self):
100- CodeImportBaseView.setUpWidgets(self)
101+ super(CodeImportNewView, self).setUpWidgets()
102
103 # Extract the radio buttons from the rcs_type widget, so we can
104 # display them separately in the form.
105@@ -542,9 +540,11 @@
106 self.code_import = self.context.code_import
107 if self.code_import is None:
108 raise NotFoundError
109+ if not self._super_user:
110+ raise Unauthorized
111 # The next and cancel location is the branch details page.
112 self.cancel_url = self.next_url = canonical_url(self.context)
113- CodeImportBaseView.initialize(self)
114+ super(CodeImportEditView, self).initialize()
115
116 @property
117 def adapters(self):
118
119=== modified file 'lib/lp/code/browser/tests/test_codeimport.py'
120--- lib/lp/code/browser/tests/test_codeimport.py 2012-10-02 07:45:15 +0000
121+++ lib/lp/code/browser/tests/test_codeimport.py 2012-10-02 23:35:24 +0000
122@@ -1,4 +1,4 @@
123-# Copyright 2009 Canonical Ltd. This software is licensed under the
124+# Copyright 2009-2012 Canonical Ltd. This software is licensed under the
125 # GNU Affero General Public License version 3 (see the file LICENSE).
126
127 """Tests for the code import browser code."""
128@@ -7,14 +7,20 @@
129
130 import re
131
132+from zope.security.interfaces import Unauthorized
133+
134 from lp.code.enums import RevisionControlSystems
135 from lp.services.webapp import canonical_url
136-from lp.testing import TestCaseWithFactory
137+from lp.testing import (
138+ person_logged_in,
139+ TestCaseWithFactory,
140+ )
141 from lp.testing.layers import DatabaseFunctionalLayer
142 from lp.testing.pages import (
143 extract_text,
144 find_tag_by_id,
145 )
146+from lp.testing.views import create_initialized_view
147
148
149 class TestImportDetails(TestCaseWithFactory):
150@@ -53,3 +59,11 @@
151 svn_details = find_tag_by_id(browser.contents, 'svn-import-details')
152 self.assertSvnDetailsDisplayed(
153 svn_details, RevisionControlSystems.SVN)
154+
155+ def test_branch_owner_of_import_forbidden(self):
156+ # Unauthorized users are forbidden to edit an import.
157+ cimport = self.factory.makeCodeImport()
158+ with person_logged_in(cimport.branch.owner):
159+ self.assertRaises(
160+ Unauthorized, create_initialized_view, cimport.branch,
161+ '+edit-import')
162
163=== modified file 'lib/lp/code/model/branch.py'
164--- lib/lp/code/model/branch.py 2012-10-02 07:45:15 +0000
165+++ lib/lp/code/model/branch.py 2012-10-02 23:35:24 +0000
166@@ -1,8 +1,6 @@
167 # Copyright 2009-2012 Canonical Ltd. This software is licensed under the
168 # GNU Affero General Public License version 3 (see the file LICENSE).
169
170-# pylint: disable-msg=E0611,W0212,W0141,F0401
171-
172 __metaclass__ = type
173 __all__ = [
174 'Branch',
175
176=== modified file 'lib/lp/code/model/codeimport.py'
177--- lib/lp/code/model/codeimport.py 2012-10-02 07:45:15 +0000
178+++ lib/lp/code/model/codeimport.py 2012-10-02 23:35:24 +0000
179@@ -1,8 +1,6 @@
180-# Copyright 2009-2011 Canonical Ltd. This software is licensed under the
181+# Copyright 2009-2012 Canonical Ltd. This software is licensed under the
182 # GNU Affero General Public License version 3 (see the file LICENSE).
183
184-# pylint: disable-msg=E0611,W0212
185-
186 """Database classes including and related to CodeImport."""
187
188 __metaclass__ = type
189@@ -148,13 +146,6 @@
190 if job is not None:
191 if job.state == CodeImportJobState.PENDING:
192 CodeImportJobWorkflow().deletePendingJob(self)
193- else:
194- # When we have job killing, we might want to kill a running
195- # job.
196- pass
197- else:
198- # No job, so nothing to do.
199- pass
200
201 results = SQLMultipleJoin(
202 'CodeImportResult', joinColumn='code_import',
203@@ -239,7 +230,6 @@
204 else:
205 getUtility(ICodeImportJobWorkflow).requestJob(
206 self.import_job, requester)
207- return None
208
209
210 class CodeImportSet: