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

Proposed by Steve Kowalik
Status: Merged
Approved by: Steve Kowalik
Approved revision: no longer in the source branch.
Merged at revision: 16065
Proposed branch: lp:~stevenk/launchpad/no-edit-import-for-you
Merge into: lp:launchpad
Diff against target: 195 lines (+25/-33)
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 (+9/-1)
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
Reviewer Review Type Date Requested Status
Ian Booth (community) Approve
Review via email: mp+127417@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

Raise Unauthorized if the user isn't an admin or in vcs imports on IBranch:+edit-import. Due to the ZCML, the branch owner is allowed to see the view, but will get an OOPS on submit. Cut this off at the pass by raising Unauthorized in the view's initialize method.

Clean up for net-negative LoC.

To post a comment you must log in.
Revision history for this message
Ian Booth (wallyworld) wrote :

Looks good

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-09-28 06:15:58 +0000
3+++ lib/lp/code/browser/branch.py 2012-10-02 05:19:21 +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-07-06 21:25:10 +0000
28+++ lib/lp/code/browser/codeimport.py 2012-10-02 05:19:21 +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-01-01 02:58:52 +0000
121+++ lib/lp/code/browser/tests/test_codeimport.py 2012-10-02 05:19:21 +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,6 +7,8 @@
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@@ -53,3 +55,9 @@
138 svn_details = find_tag_by_id(browser.contents, 'svn-import-details')
139 self.assertSvnDetailsDisplayed(
140 svn_details, RevisionControlSystems.SVN)
141+
142+ def test_branch_owner_of_import_forbidden(self):
143+ cimport = self.factory.makeCodeImport()
144+ url = canonical_url(cimport.branch, view_name='+edit-import')
145+ self.assertRaises(
146+ Unauthorized, self.getUserBrowser(url, user=cimport.branch.owner))
147
148=== modified file 'lib/lp/code/model/branch.py'
149--- lib/lp/code/model/branch.py 2012-09-26 07:59:35 +0000
150+++ lib/lp/code/model/branch.py 2012-10-02 05:19:21 +0000
151@@ -1,8 +1,6 @@
152 # Copyright 2009-2012 Canonical Ltd. This software is licensed under the
153 # GNU Affero General Public License version 3 (see the file LICENSE).
154
155-# pylint: disable-msg=E0611,W0212,W0141,F0401
156-
157 __metaclass__ = type
158 __all__ = [
159 'Branch',
160
161=== modified file 'lib/lp/code/model/codeimport.py'
162--- lib/lp/code/model/codeimport.py 2011-12-30 06:14:56 +0000
163+++ lib/lp/code/model/codeimport.py 2012-10-02 05:19:21 +0000
164@@ -1,8 +1,6 @@
165-# Copyright 2009-2011 Canonical Ltd. This software is licensed under the
166+# Copyright 2009-2012 Canonical Ltd. This software is licensed under the
167 # GNU Affero General Public License version 3 (see the file LICENSE).
168
169-# pylint: disable-msg=E0611,W0212
170-
171 """Database classes including and related to CodeImport."""
172
173 __metaclass__ = type
174@@ -148,13 +146,6 @@
175 if job is not None:
176 if job.state == CodeImportJobState.PENDING:
177 CodeImportJobWorkflow().deletePendingJob(self)
178- else:
179- # When we have job killing, we might want to kill a running
180- # job.
181- pass
182- else:
183- # No job, so nothing to do.
184- pass
185
186 results = SQLMultipleJoin(
187 'CodeImportResult', joinColumn='code_import',
188@@ -239,7 +230,6 @@
189 else:
190 getUtility(ICodeImportJobWorkflow).requestJob(
191 self.import_job, requester)
192- return None
193
194
195 class CodeImportSet: