Merge lp:~edwin-grubbs/launchpad/bug-451208-subscribing-reveals-email into lp:launchpad

Proposed by Edwin Grubbs
Status: Merged
Merged at revision: not available
Proposed branch: lp:~edwin-grubbs/launchpad/bug-451208-subscribing-reveals-email
Merge into: lp:launchpad
Diff against target: 1808 lines (+788/-258)
16 files modified
lib/canonical/launchpad/browser/vocabulary.py (+5/-1)
lib/canonical/launchpad/doc/vocabularies.txt (+8/-5)
lib/canonical/launchpad/doc/vocabulary-json.txt (+20/-0)
lib/canonical/launchpad/vocabularies/configure.zcml (+297/-86)
lib/canonical/launchpad/vocabularies/dbobjects.py (+5/-3)
lib/canonical/launchpad/webapp/configure.zcml (+1/-0)
lib/canonical/launchpad/webapp/metazcml.py (+7/-2)
lib/canonical/launchpad/zcml/binaryandsourcepackagename.zcml (+13/-2)
lib/lp/answers/configure.zcml (+9/-2)
lib/lp/answers/doc/faq-vocabulary.txt (+2/-1)
lib/lp/registry/doc/vocabularies.txt (+57/-56)
lib/lp/registry/vocabularies.zcml (+304/-95)
lib/lp/services/tests/test_vocabularies.py (+37/-0)
lib/lp/services/worlddata/vocabularies.zcml (+5/-2)
lib/lp/soyuz/configure.zcml (+16/-2)
lib/lp/soyuz/interfaces/binarypackagename.py (+2/-1)
To merge this branch: bzr merge lp:~edwin-grubbs/launchpad/bug-451208-subscribing-reveals-email
Reviewer Review Type Date Requested Status
Guilherme Salgado (community) code Approve
Canonical Launchpad Engineering code Pending
Review via email: mp+17261@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Edwin Grubbs (edwin-grubbs) wrote :

Summary
-------

Registered all the Launchpad vocabularies with <securedutility>
instead of <utility> so that it will not be possible to get
a db object without a security proxy.

This required an <allow> block on each utility to allow
access to the __call__ method on the vocabulary class (IVocabularyFactory).

The vocabulary objects required a <class> directive with
<allow interface=IHugeVocabulary>.

Some vocabulary factories were actually functions, such as
BugNominatableSeriesVocabulary, which would actually return either
BugNominatableProductSeriesVocabulary or BugNominatableDistroSeriesVocabulary
objects.

Implementation details
----------------------

New tests:
    lib/lp/services/tests/test_vocabularies.py
    lib/canonical/launchpad/doc/vocabulary-json.txt

Indicate in the picker widget when email address is hidden.
    lib/canonical/launchpad/browser/vocabulary.py

Some vocabularies need to get the IBinaryAndSourcePackageName.id
attribute from objects that were passed in from widgets, so they
are already security proxied.
    lib/lp/soyuz/interfaces/binarypackagename.py

Fixed tests that broke since they were accessing methods that
should not be exposed through the security proxy.
    lib/canonical/launchpad/doc/vocabularies.txt
    lib/lp/answers/doc/faq-vocabulary.txt
    lib/lp/registry/doc/vocabularies.txt

Since vocabularies must be registered with a name parameter,
the <securedutility> directive needed to be updated to pass
this along to the underlying <utility>.
    lib/canonical/launchpad/webapp/metazcml.py

Added BugNominatableDistroSeriesVocabulary and
BugNominatableProductSeriesVocabulary to __all__.
    lib/canonical/launchpad/vocabularies/dbobjects.py

ICountableIterator defines a __getitem__ method that provides
the __getslice__ functionality.
    lib/canonical/launchpad/webapp/configure.zcml

Somewhat interesting zcml changes:
    lib/canonical/launchpad/zcml/binaryandsourcepackagename.zcml
    lib/lp/soyuz/configure.zcml

The changes for SimpleVocabulary, SimpleTerm, and
BugNominatable*SeriesVocabulary are the only parts of note among the
many changes in this file.
    lib/canonical/launchpad/vocabularies/configure.zcml

TimezoneNameVocabulary is just a function that returns a
SimpleVocabulary, so it doesn't need any <class> directives.
    lib/lp/services/worlddata/vocabularies.zcml

Uninteresting bulk changes to use <securedutility>:
    lib/lp/answers/configure.zcml
    lib/lp/registry/vocabularies.zcml

Tests
-----

./bin/test -vv -t 'test_vocabularies|vocabulary-json.txt'

Demo and Q/A
------------

* Open https://launchpad.dev/people/+requestmerge
  * Click on "Choose" to bring up the picker.
  * Search for "name12".
  * The email address should be hidden.

Revision history for this message
Guilherme Salgado (salgado) wrote :
Download full text (9.1 KiB)

> === modified file 'lib/canonical/launchpad/webapp/configure.zcml'
> --- lib/canonical/launchpad/webapp/configure.zcml 2009-11-18 00:22:41 +0000
> +++ lib/canonical/launchpad/webapp/configure.zcml 2010-01-12 22:36:26 +0000
> @@ -809,6 +809,7 @@
>
> <class class="canonical.launchpad.webapp.vocabulary.CountableIterator">
> <allow interface="canonical.launchpad.webapp.vocabulary.ICountableIterator" />
> + <allow attributes="__getslice__"/>

Wouldn't it make sense to add __getslice__ to CountableIterator?

> </class>
>
> <class class="canonical.launchpad.webapp.vocabulary.BatchedCountableIterator">
>
> === modified file 'lib/lp/registry/doc/vocabularies.txt'
> --- lib/lp/registry/doc/vocabularies.txt 2009-12-24 01:41:54 +0000
> +++ lib/lp/registry/doc/vocabularies.txt 2010-01-12 22:36:26 +0000
> @@ -20,7 +20,9 @@
> The active mailing lists vocabulary matches and returns only those mailing
> lists which are active.
>
> - >>> list_vocabulary = vocabulary_registry.get(None, 'ActiveMailingList')
> + >>> from zope.security.proxy import removeSecurityProxy
> + >>> list_vocabulary = removeSecurityProxy(
> + ... vocabulary_registry.get(None, 'ActiveMailingList'))
> >>> from canonical.launchpad.webapp.testing import verifyObject
> >>> from canonical.launchpad.webapp.vocabulary import IHugeVocabulary
> >>> verifyObject(IHugeVocabulary, list_vocabulary)
> @@ -203,6 +205,7 @@
> u'The Hoary Hedgehog Release'
>
> >>> def getTerms(vocab, search_text):
> + ... vocab = removeSecurityProxy(vocab)
> ... [vocab.toTerm(item) for item in vocab.search(search_text)]
>
> >>> getTerms(distroseries_vocabulary, 'woody')
> @@ -508,7 +511,8 @@
>
> The list of selectable projects. The results are ordered by displayname.
>
> - >>> project_vocabulary = vocabulary_registry.get(None, "Project")
> + >>> project_vocabulary = removeSecurityProxy(
> + ... vocabulary_registry.get(None, "Project"))

I think we wought to have a wrapper around vocabulary_registry.get() to remove
the security proxy of the vocab before returning. Something like

    def get_naked_vocab(context, name):
        return removeSecurityProxy(vocab_registry.get(context, name))

That way we don't have to repeat the removeSecurityProxy() call in all the
places we call vocabulary_registry.get.

> >>> project_vocabulary.displayname
> 'Select a project group'
>
> @@ -542,7 +546,8 @@
>
> The list of selectable products. Results are ordered by displayname.
>
> - >>> product_vocabulary = vocabulary_registry.get(None, "Product")
> + >>> product_vocabulary = removeSecurityProxy(
> + ... vocabulary_registry.get(None, "Product"))
> >>> product_vocabulary.displayname
> 'Select a project'
>
> @@ -583,8 +588,8 @@
>
> The list of selectable products releases.
>
> - >>> productrelease_vocabulary = vocabulary_registry.get(None,
> - ... "ProductRelease")
> + >>> productrelease_vocabulary = removeSecurityProxy(
> + ... vocabulary_registry.get(None, "ProductRelease"))
> >>> productrelease_vocabular...

Read more...

review: Needs Fixing (code)
Revision history for this message
Guilherme Salgado (salgado) wrote :
Download full text (9.1 KiB)

> === modified file 'lib/canonical/launchpad/webapp/configure.zcml'
> --- lib/canonical/launchpad/webapp/configure.zcml 2009-11-18 00:22:41 +0000
> +++ lib/canonical/launchpad/webapp/configure.zcml 2010-01-12 22:36:26 +0000
> @@ -809,6 +809,7 @@
>
> <class class="canonical.launchpad.webapp.vocabulary.CountableIterator">
> <allow interface="canonical.launchpad.webapp.vocabulary.ICountableIterator" />
> + <allow attributes="__getslice__"/>

Wouldn't it make sense to add __getslice__ to CountableIterator?

> </class>
>
> <class class="canonical.launchpad.webapp.vocabulary.BatchedCountableIterator">
>
> === modified file 'lib/lp/registry/doc/vocabularies.txt'
> --- lib/lp/registry/doc/vocabularies.txt 2009-12-24 01:41:54 +0000
> +++ lib/lp/registry/doc/vocabularies.txt 2010-01-12 22:36:26 +0000
> @@ -20,7 +20,9 @@
> The active mailing lists vocabulary matches and returns only those mailing
> lists which are active.
>
> - >>> list_vocabulary = vocabulary_registry.get(None, 'ActiveMailingList')
> + >>> from zope.security.proxy import removeSecurityProxy
> + >>> list_vocabulary = removeSecurityProxy(
> + ... vocabulary_registry.get(None, 'ActiveMailingList'))
> >>> from canonical.launchpad.webapp.testing import verifyObject
> >>> from canonical.launchpad.webapp.vocabulary import IHugeVocabulary
> >>> verifyObject(IHugeVocabulary, list_vocabulary)
> @@ -203,6 +205,7 @@
> u'The Hoary Hedgehog Release'
>
> >>> def getTerms(vocab, search_text):
> + ... vocab = removeSecurityProxy(vocab)
> ... [vocab.toTerm(item) for item in vocab.search(search_text)]
>
> >>> getTerms(distroseries_vocabulary, 'woody')
> @@ -508,7 +511,8 @@
>
> The list of selectable projects. The results are ordered by displayname.
>
> - >>> project_vocabulary = vocabulary_registry.get(None, "Project")
> + >>> project_vocabulary = removeSecurityProxy(
> + ... vocabulary_registry.get(None, "Project"))

I think we wought to have a wrapper around vocabulary_registry.get() to remove
the security proxy of the vocab before returning. Something like

    def get_naked_vocab(context, name):
        return removeSecurityProxy(vocab_registry.get(context, name))

That way we don't have to repeat the removeSecurityProxy() call in all the
places we call vocabulary_registry.get.

> >>> project_vocabulary.displayname
> 'Select a project group'
>
> @@ -542,7 +546,8 @@
>
> The list of selectable products. Results are ordered by displayname.
>
> - >>> product_vocabulary = vocabulary_registry.get(None, "Product")
> + >>> product_vocabulary = removeSecurityProxy(
> + ... vocabulary_registry.get(None, "Product"))
> >>> product_vocabulary.displayname
> 'Select a project'
>
> @@ -583,8 +588,8 @@
>
> The list of selectable products releases.
>
> - >>> productrelease_vocabulary = vocabulary_registry.get(None,
> - ... "ProductRelease")
> + >>> productrelease_vocabulary = removeSecurityProxy(
> + ... vocabulary_registry.get(None, "ProductRelease"))
> >>> productrelease_vocabular...

Read more...

review: Needs Fixing (code)
Revision history for this message
Edwin Grubbs (edwin-grubbs) wrote :
Download full text (30.9 KiB)

> > === modified file 'lib/canonical/launchpad/webapp/configure.zcml'
> > --- lib/canonical/launchpad/webapp/configure.zcml 2009-11-18 00:22:41
> +0000
> > +++ lib/canonical/launchpad/webapp/configure.zcml 2010-01-12 22:36:26
> +0000
> > @@ -809,6 +809,7 @@
> >
> > <class class="canonical.launchpad.webapp.vocabulary.CountableIterator">
> > <allow
> interface="canonical.launchpad.webapp.vocabulary.ICountableIterator" />
> > + <allow attributes="__getslice__"/>
>
> Wouldn't it make sense to add __getslice__ to CountableIterator?

Gary had recommended that I add __getslice__ to the zcml instead of the interface
since this is a security concern and not a method that implementors of ICountableIterator
need to create.

> > </class>
> >
> > <class
> class="canonical.launchpad.webapp.vocabulary.BatchedCountableIterator">
> >
> > === modified file 'lib/lp/registry/doc/vocabularies.txt'
> > --- lib/lp/registry/doc/vocabularies.txt 2009-12-24 01:41:54 +0000
> > +++ lib/lp/registry/doc/vocabularies.txt 2010-01-12 22:36:26 +0000
> > @@ -20,7 +20,9 @@
> > The active mailing lists vocabulary matches and returns only those mailing
> > lists which are active.
> >
> > - >>> list_vocabulary = vocabulary_registry.get(None,
> 'ActiveMailingList')
> > + >>> from zope.security.proxy import removeSecurityProxy
> > + >>> list_vocabulary = removeSecurityProxy(
> > + ... vocabulary_registry.get(None, 'ActiveMailingList'))
> > >>> from canonical.launchpad.webapp.testing import verifyObject
> > >>> from canonical.launchpad.webapp.vocabulary import IHugeVocabulary
> > >>> verifyObject(IHugeVocabulary, list_vocabulary)
> > @@ -203,6 +205,7 @@
> > u'The Hoary Hedgehog Release'
> >
> > >>> def getTerms(vocab, search_text):
> > + ... vocab = removeSecurityProxy(vocab)
> > ... [vocab.toTerm(item) for item in vocab.search(search_text)]
> >
> > >>> getTerms(distroseries_vocabulary, 'woody')
> > @@ -508,7 +511,8 @@
> >
> > The list of selectable projects. The results are ordered by displayname.
> >
> > - >>> project_vocabulary = vocabulary_registry.get(None, "Project")
> > + >>> project_vocabulary = removeSecurityProxy(
> > + ... vocabulary_registry.get(None, "Project"))
>
> I think we wought to have a wrapper around vocabulary_registry.get() to remove
> the security proxy of the vocab before returning. Something like
>
> def get_naked_vocab(context, name):
> return removeSecurityProxy(vocab_registry.get(context, name))
>
> That way we don't have to repeat the removeSecurityProxy() call in all the
> places we call vocabulary_registry.get.

Done.

> > >>> project_vocabulary.displayname
> > 'Select a project group'
> >
> > @@ -542,7 +546,8 @@
> >
> > The list of selectable products. Results are ordered by displayname.
> >
> > - >>> product_vocabulary = vocabulary_registry.get(None, "Product")
> > + >>> product_vocabulary = removeSecurityProxy(
> > + ... vocabulary_registry.get(None, "Product"))
> > >>> product_vocabulary.displayname
> > 'Select a project'
> >
> > @@ -583,8 +588,8 @@
> >
> > The list of sel...

Revision history for this message
Guilherme Salgado (salgado) wrote :

Just add a comment explaining why we need the "vocab.__module__[:5] != 'zope.'" check in the test and it's good to go. Nice work!

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/canonical/launchpad/browser/vocabulary.py'
2--- lib/canonical/launchpad/browser/vocabulary.py 2010-01-11 17:47:52 +0000
3+++ lib/canonical/launchpad/browser/vocabulary.py 2010-01-18 21:51:20 +0000
4@@ -23,6 +23,7 @@
5 from zope.component.interfaces import ComponentLookupError
6 from zope.interface import Attribute, implements, Interface
7 from zope.app.form.interfaces import MissingInputError
8+from zope.security.interfaces import Unauthorized
9
10 from lazr.restful.interfaces import IWebServiceClientRequest
11
12@@ -83,7 +84,10 @@
13 """Adapts IPerson to IPickerEntry."""
14 extra = default_pickerentry_adapter(person)
15 if person.preferredemail is not None:
16- extra.description = person.preferredemail.email
17+ try:
18+ extra.description = person.preferredemail.email
19+ except Unauthorized:
20+ extra.description = '<email address hidden>'
21 return extra
22
23 @implementer(IPickerEntry)
24
25=== modified file 'lib/canonical/launchpad/doc/vocabularies.txt'
26--- lib/canonical/launchpad/doc/vocabularies.txt 2009-10-26 18:40:04 +0000
27+++ lib/canonical/launchpad/doc/vocabularies.txt 2010-01-18 21:51:20 +0000
28@@ -43,7 +43,11 @@
29 vocabulary registry.
30
31 >>> from zope.schema.vocabulary import getVocabularyRegistry
32+ >>> from zope.security.proxy import removeSecurityProxy
33 >>> vocabulary_registry = getVocabularyRegistry()
34+ >>> def get_naked_vocab(context, name):
35+ ... return removeSecurityProxy(
36+ ... vocabulary_registry.get(context, name))
37 >>> product_vocabulary = vocabulary_registry.get(None, "Product")
38 >>> product_vocabulary.displayname
39 'Select a project'
40@@ -56,7 +60,7 @@
41
42 All the distributions that use Malone as their main bug tracker.
43
44- >>> using_malone_vocabulary = vocabulary_registry.get(
45+ >>> using_malone_vocabulary = get_naked_vocab(
46 ... None, 'DistributionUsingMalone')
47 >>> len(using_malone_vocabulary)
48 2
49@@ -358,7 +362,7 @@
50 concerned).
51
52 # Just use None as the context.
53- >>> branch_vocabulary = vocabulary_registry.get(None, "Branch")
54+ >>> branch_vocabulary = get_naked_vocab(None, "Branch")
55 >>> def print_vocab_branches(vocab, search):
56 ... for term in vocab.searchForTerms(search):
57 ... print term.value.unique_name
58@@ -639,8 +643,7 @@
59 that matches the search string. The string is matched against the name,
60 or fallbacks to a full text search.
61
62- >>> vocab = vocabulary_registry.get(
63- ... spec_a, "SpecificationDepCandidates")
64+ >>> vocab = get_naked_vocab(spec_a, "SpecificationDepCandidates")
65 >>> list(vocab.search('spec-b')) == [spec_b]
66 True
67 >>> list(vocab.search('third')) == [spec_c]
68@@ -664,7 +667,7 @@
69 >>> from canonical.launchpad.webapp.testing import verifyObject
70 >>> from canonical.launchpad.webapp.vocabulary import IHugeVocabulary
71
72- >>> vocabulary = vocabulary_registry.get(None, 'PPA')
73+ >>> vocabulary = get_naked_vocab(None, 'PPA')
74 >>> verifyObject(IHugeVocabulary, vocabulary)
75 True
76
77
78=== modified file 'lib/canonical/launchpad/doc/vocabulary-json.txt'
79--- lib/canonical/launchpad/doc/vocabulary-json.txt 2009-07-28 13:48:07 +0000
80+++ lib/canonical/launchpad/doc/vocabulary-json.txt 2010-01-18 21:51:20 +0000
81@@ -121,3 +121,23 @@
82 ],
83 "total_size": 1
84 }
85+
86+Hidden email addresses should also be hidden when IPerson objects are
87+retrieved through vocabularies.
88+
89+ >>> form = dict(name='ValidPersonOrTeam', search_text='name12',
90+ ... start='0', batch='1')
91+ >>> view = create_vocabulary_view(form)
92+ >>> print_json(view())
93+ {
94+ "entries": [
95+ {
96+ "api_uri": "/~name12",
97+ "css": "sprite person",
98+ "description": "<email address hidden>",
99+ "title": "Sample Person",
100+ "value": "name12"
101+ }
102+ ],
103+ "total_size": 1
104+ }
105
106=== modified file 'lib/canonical/launchpad/vocabularies/configure.zcml'
107--- lib/canonical/launchpad/vocabularies/configure.zcml 2009-10-26 18:40:04 +0000
108+++ lib/canonical/launchpad/vocabularies/configure.zcml 2010-01-18 21:51:20 +0000
109@@ -4,177 +4,388 @@
110
111 <configure xmlns="http://namespaces.zope.org/zope">
112
113- <utility
114+ <class class="zope.schema.vocabulary.SimpleVocabulary">
115+ <allow interface="zope.schema.interfaces.IVocabularyTokenized"/>
116+ </class>
117+
118+ <class class="zope.schema.vocabulary.SimpleTerm">
119+ <allow interface="zope.schema.interfaces.ITitledTokenizedTerm"/>
120+ </class>
121+
122+ <securedutility
123 name="Branch"
124 component="canonical.launchpad.vocabularies.BranchVocabulary"
125 provides="zope.schema.interfaces.IVocabularyFactory"
126- />
127-
128- <utility
129+ >
130+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
131+ </securedutility>
132+
133+ <class class="canonical.launchpad.vocabularies.BranchVocabulary">
134+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
135+ </class>
136+
137+
138+ <securedutility
139 name="HostedBranchRestrictedOnOwner"
140 component="canonical.launchpad.vocabularies.HostedBranchRestrictedOnOwnerVocabulary"
141 provides="zope.schema.interfaces.IVocabularyFactory"
142- />
143-
144- <utility
145+ >
146+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
147+ </securedutility>
148+
149+ <class class="canonical.launchpad.vocabularies.HostedBranchRestrictedOnOwnerVocabulary">
150+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
151+ </class>
152+
153+
154+ <securedutility
155 name="BranchRestrictedOnProduct"
156 component="canonical.launchpad.vocabularies.BranchRestrictedOnProductVocabulary"
157 provides="zope.schema.interfaces.IVocabularyFactory"
158- />
159-
160- <utility
161+ >
162+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
163+ </securedutility>
164+
165+ <class class="canonical.launchpad.vocabularies.BranchRestrictedOnProductVocabulary">
166+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
167+ </class>
168+
169+
170+ <securedutility
171 name="Bug"
172 component="canonical.launchpad.vocabularies.BugVocabulary"
173 provides="zope.schema.interfaces.IVocabularyFactory"
174- />
175-
176- <utility
177+ >
178+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
179+ </securedutility>
180+
181+ <class class="canonical.launchpad.vocabularies.BugVocabulary">
182+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
183+ </class>
184+
185+
186+ <securedutility
187 name="BugNominatableSeries"
188 component="canonical.launchpad.vocabularies.BugNominatableSeriesVocabulary"
189 provides="zope.schema.interfaces.IVocabularyFactory"
190- />
191-
192- <utility
193+ >
194+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
195+ </securedutility>
196+
197+ <class class="canonical.launchpad.vocabularies.BugNominatableProductSeriesVocabulary">
198+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
199+ </class>
200+
201+ <class class="canonical.launchpad.vocabularies.BugNominatableDistroSeriesVocabulary">
202+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
203+ </class>
204+
205+
206+ <securedutility
207 name="BugTracker"
208 component="canonical.launchpad.vocabularies.BugTrackerVocabulary"
209 provides="zope.schema.interfaces.IVocabularyFactory"
210- />
211-
212- <utility
213+ >
214+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
215+ </securedutility>
216+
217+ <class class="canonical.launchpad.vocabularies.BugTrackerVocabulary">
218+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
219+ </class>
220+
221+
222+ <securedutility
223 name="BugWatch"
224 component="canonical.launchpad.vocabularies.BugWatchVocabulary"
225 provides="zope.schema.interfaces.IVocabularyFactory"
226- />
227-
228- <utility
229+ >
230+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
231+ </securedutility>
232+
233+ <class class="canonical.launchpad.vocabularies.BugWatchVocabulary">
234+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
235+ </class>
236+
237+
238+ <securedutility
239 name="Component"
240 component="canonical.launchpad.vocabularies.ComponentVocabulary"
241 provides="zope.schema.interfaces.IVocabularyFactory"
242- />
243-
244- <utility
245+ >
246+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
247+ </securedutility>
248+
249+ <class class="canonical.launchpad.vocabularies.ComponentVocabulary">
250+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
251+ </class>
252+
253+
254+ <securedutility
255 name="CountryName"
256 component="canonical.launchpad.vocabularies.CountryNameVocabulary"
257 provides="zope.schema.interfaces.IVocabularyFactory"
258- />
259-
260- <utility
261+ >
262+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
263+ </securedutility>
264+
265+ <class class="canonical.launchpad.vocabularies.CountryNameVocabulary">
266+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
267+ </class>
268+
269+
270+ <securedutility
271 name="DistributionUsingMalone"
272 component="canonical.launchpad.vocabularies.DistributionUsingMaloneVocabulary"
273 provides="zope.schema.interfaces.IVocabularyFactory"
274- />
275-
276- <utility
277+ >
278+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
279+ </securedutility>
280+
281+ <class class="canonical.launchpad.vocabularies.DistributionUsingMaloneVocabulary">
282+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
283+ </class>
284+
285+
286+ <securedutility
287 name="FilteredDeltaLanguagePack"
288 component="canonical.launchpad.vocabularies.FilteredDeltaLanguagePackVocabulary"
289 provides="zope.schema.interfaces.IVocabularyFactory"
290- />
291-
292- <utility
293+ >
294+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
295+ </securedutility>
296+
297+ <class class="canonical.launchpad.vocabularies.FilteredDeltaLanguagePackVocabulary">
298+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
299+ </class>
300+
301+
302+ <securedutility
303 name="FilteredDistroArchSeries"
304 component="canonical.launchpad.vocabularies.FilteredDistroArchSeriesVocabulary"
305 provides="zope.schema.interfaces.IVocabularyFactory"
306- />
307-
308- <utility
309+ >
310+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
311+ </securedutility>
312+
313+ <class class="canonical.launchpad.vocabularies.FilteredDistroArchSeriesVocabulary">
314+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
315+ </class>
316+
317+
318+ <securedutility
319 name="FilteredFullLanguagePack"
320 component="canonical.launchpad.vocabularies.FilteredFullLanguagePackVocabulary"
321 provides="zope.schema.interfaces.IVocabularyFactory"
322- />
323-
324- <utility
325+ >
326+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
327+ </securedutility>
328+
329+ <class class="canonical.launchpad.vocabularies.FilteredFullLanguagePackVocabulary">
330+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
331+ </class>
332+
333+
334+ <securedutility
335 name="FilteredLanguagePack"
336 component="canonical.launchpad.vocabularies.FilteredLanguagePackVocabulary"
337 provides="zope.schema.interfaces.IVocabularyFactory"
338- />
339-
340- <utility
341+ >
342+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
343+ </securedutility>
344+
345+ <class class="canonical.launchpad.vocabularies.FilteredLanguagePackVocabulary">
346+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
347+ </class>
348+
349+
350+ <securedutility
351 name="FutureSprint"
352 component="canonical.launchpad.vocabularies.FutureSprintVocabulary"
353 provides="zope.schema.interfaces.IVocabularyFactory"
354- />
355-
356- <utility
357+ >
358+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
359+ </securedutility>
360+
361+ <class class="canonical.launchpad.vocabularies.FutureSprintVocabulary">
362+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
363+ </class>
364+
365+
366+ <securedutility
367 name="Language"
368 component="canonical.launchpad.vocabularies.LanguageVocabulary"
369 provides="zope.schema.interfaces.IVocabularyFactory"
370- />
371-
372- <utility
373+ >
374+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
375+ </securedutility>
376+
377+ <class class="canonical.launchpad.vocabularies.LanguageVocabulary">
378+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
379+ </class>
380+
381+
382+ <securedutility
383 name="TranslatableLanguage"
384 component="canonical.launchpad.vocabularies.TranslatableLanguageVocabulary"
385 provides="zope.schema.interfaces.IVocabularyFactory"
386- />
387-
388- <utility
389+ >
390+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
391+ </securedutility>
392+
393+ <class class="canonical.launchpad.vocabularies.TranslatableLanguageVocabulary">
394+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
395+ </class>
396+
397+
398+ <securedutility
399 name="PackageRelease"
400 component="canonical.launchpad.vocabularies.PackageReleaseVocabulary"
401 provides="zope.schema.interfaces.IVocabularyFactory"
402- />
403-
404- <utility
405+ >
406+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
407+ </securedutility>
408+
409+ <class class="canonical.launchpad.vocabularies.PackageReleaseVocabulary">
410+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
411+ </class>
412+
413+
414+ <securedutility
415 name="PPA"
416 component="canonical.launchpad.vocabularies.PPAVocabulary"
417 provides="zope.schema.interfaces.IVocabularyFactory"
418- />
419-
420- <utility
421+ >
422+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
423+ </securedutility>
424+
425+ <class class="canonical.launchpad.vocabularies.PPAVocabulary">
426+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
427+ </class>
428+
429+
430+ <securedutility
431 name="ProjectProductsUsingMalone"
432 component="canonical.launchpad.vocabularies.project_products_using_malone_vocabulary_factory"
433 provides="zope.schema.interfaces.IVocabularyFactory"
434- />
435-
436- <utility
437+ >
438+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
439+ </securedutility>
440+
441+
442+ <securedutility
443 name="Specification"
444 component="canonical.launchpad.vocabularies.SpecificationVocabulary"
445 provides="zope.schema.interfaces.IVocabularyFactory"
446- />
447-
448- <utility
449+ >
450+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
451+ </securedutility>
452+
453+ <class class="canonical.launchpad.vocabularies.SpecificationVocabulary">
454+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
455+ </class>
456+
457+
458+ <securedutility
459 name="SpecificationDependencies"
460 component="canonical.launchpad.vocabularies.SpecificationDependenciesVocabulary"
461 provides="zope.schema.interfaces.IVocabularyFactory"
462- />
463-
464- <utility
465+ >
466+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
467+ </securedutility>
468+
469+ <class class="canonical.launchpad.vocabularies.SpecificationDependenciesVocabulary">
470+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
471+ </class>
472+
473+
474+ <securedutility
475 name="SpecificationDepCandidates"
476 component="canonical.launchpad.vocabularies.SpecificationDepCandidatesVocabulary"
477 provides="zope.schema.interfaces.IVocabularyFactory"
478- />
479-
480- <utility
481+ >
482+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
483+ </securedutility>
484+
485+ <class class="canonical.launchpad.vocabularies.SpecificationDepCandidatesVocabulary">
486+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
487+ </class>
488+
489+
490+ <securedutility
491 name="Sprint"
492 component="canonical.launchpad.vocabularies.SprintVocabulary"
493 provides="zope.schema.interfaces.IVocabularyFactory"
494- />
495-
496- <utility
497+ >
498+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
499+ </securedutility>
500+
501+ <class class="canonical.launchpad.vocabularies.SprintVocabulary">
502+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
503+ </class>
504+
505+
506+ <securedutility
507 name="TranslationGroup"
508 component="canonical.launchpad.vocabularies.TranslationGroupVocabulary"
509 provides="zope.schema.interfaces.IVocabularyFactory"
510- />
511-
512- <utility
513+ >
514+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
515+ </securedutility>
516+
517+ <class class="canonical.launchpad.vocabularies.TranslationGroupVocabulary">
518+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
519+ </class>
520+
521+
522+ <securedutility
523 name="TranslationMessage"
524 component="canonical.launchpad.vocabularies.TranslationMessageVocabulary"
525 provides="zope.schema.interfaces.IVocabularyFactory"
526- />
527-
528- <utility
529+ >
530+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
531+ </securedutility>
532+
533+ <class class="canonical.launchpad.vocabularies.TranslationMessageVocabulary">
534+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
535+ </class>
536+
537+
538+ <securedutility
539 name="TranslationTemplate"
540 component="canonical.launchpad.vocabularies.TranslationTemplateVocabulary"
541 provides="zope.schema.interfaces.IVocabularyFactory"
542- />
543-
544- <utility
545+ >
546+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
547+ </securedutility>
548+
549+ <class class="canonical.launchpad.vocabularies.TranslationTemplateVocabulary">
550+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
551+ </class>
552+
553+
554+ <securedutility
555 name="Processor"
556 component="canonical.launchpad.vocabularies.ProcessorVocabulary"
557 provides="zope.schema.interfaces.IVocabularyFactory"
558- />
559-
560- <utility
561+ >
562+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
563+ </securedutility>
564+
565+ <class class="canonical.launchpad.vocabularies.ProcessorVocabulary">
566+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
567+ </class>
568+
569+
570+ <securedutility
571 name="ProcessorFamily"
572 component="canonical.launchpad.vocabularies.ProcessorFamilyVocabulary"
573 provides="zope.schema.interfaces.IVocabularyFactory"
574- />
575+ >
576+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
577+ </securedutility>
578+
579+ <class class="canonical.launchpad.vocabularies.ProcessorFamilyVocabulary">
580+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
581+ </class>
582+
583 </configure>
584
585=== modified file 'lib/canonical/launchpad/vocabularies/dbobjects.py'
586--- lib/canonical/launchpad/vocabularies/dbobjects.py 2009-10-26 18:40:04 +0000
587+++ lib/canonical/launchpad/vocabularies/dbobjects.py 2010-01-18 21:51:20 +0000
588@@ -10,9 +10,10 @@
589 __metaclass__ = type
590
591 __all__ = [
592- 'HostedBranchRestrictedOnOwnerVocabulary',
593 'BranchRestrictedOnProductVocabulary',
594 'BranchVocabulary',
595+ 'BugNominatableDistroSeriesVocabulary',
596+ 'BugNominatableProductSeriesVocabulary',
597 'BugNominatableSeriesVocabulary',
598 'BugTrackerVocabulary',
599 'BugVocabulary',
600@@ -25,11 +26,13 @@
601 'FilteredFullLanguagePackVocabulary',
602 'FilteredLanguagePackVocabulary',
603 'FutureSprintVocabulary',
604+ 'HostedBranchRestrictedOnOwnerVocabulary',
605 'LanguageVocabulary',
606+ 'PackageReleaseVocabulary',
607 'PPAVocabulary',
608- 'PackageReleaseVocabulary',
609 'ProcessorFamilyVocabulary',
610 'ProcessorVocabulary',
611+ 'project_products_using_malone_vocabulary_factory',
612 'SpecificationDepCandidatesVocabulary',
613 'SpecificationDependenciesVocabulary',
614 'SpecificationVocabulary',
615@@ -39,7 +42,6 @@
616 'TranslationMessageVocabulary',
617 'TranslationTemplateVocabulary',
618 'WebBugTrackerVocabulary',
619- 'project_products_using_malone_vocabulary_factory',
620 ]
621
622 import cgi
623
624=== modified file 'lib/canonical/launchpad/webapp/configure.zcml'
625--- lib/canonical/launchpad/webapp/configure.zcml 2010-01-13 13:23:20 +0000
626+++ lib/canonical/launchpad/webapp/configure.zcml 2010-01-18 21:51:20 +0000
627@@ -815,6 +815,7 @@
628
629 <class class="canonical.launchpad.webapp.vocabulary.CountableIterator">
630 <allow interface="canonical.launchpad.webapp.vocabulary.ICountableIterator" />
631+ <allow attributes="__getslice__"/>
632 </class>
633
634 <class class="canonical.launchpad.webapp.vocabulary.BatchedCountableIterator">
635
636=== modified file 'lib/canonical/launchpad/webapp/metazcml.py'
637--- lib/canonical/launchpad/webapp/metazcml.py 2009-10-21 13:11:48 +0000
638+++ lib/canonical/launchpad/webapp/metazcml.py 2010-01-18 21:51:20 +0000
639@@ -75,6 +75,8 @@
640
641 component = GlobalObject(title=u'component', required=False)
642
643+ name = TextLine(title=u"Name", required=False)
644+
645
646 class PermissionCollectingContext:
647
648@@ -97,7 +99,8 @@
649
650 class SecuredUtilityDirective:
651
652- def __init__(self, _context, provides, class_=None, component=None):
653+ def __init__(self, _context, provides, class_=None, component=None,
654+ name=''):
655 if class_ is not None:
656 assert component is None, "Both class and component specified"
657 self.component = class_()
658@@ -107,6 +110,7 @@
659 self.component = component
660 self._context = _context
661 self.provides = provides
662+ self.name = name
663 self.permission_collector = PermissionCollectingContext()
664 self.contentdirective = ClassDirective(
665 self.permission_collector, class_)
666@@ -127,7 +131,8 @@
667 self.permission_collector.set_permissions
668 )
669 component = ProxyFactory(self.component, checker=checker)
670- utility(self._context, self.provides, component=component)
671+ utility(self._context, self.provides, component=component,
672+ name=self.name)
673 return ()
674
675
676
677=== modified file 'lib/canonical/launchpad/zcml/binaryandsourcepackagename.zcml'
678--- lib/canonical/launchpad/zcml/binaryandsourcepackagename.zcml 2009-07-13 18:15:02 +0000
679+++ lib/canonical/launchpad/zcml/binaryandsourcepackagename.zcml 2010-01-18 21:51:20 +0000
680@@ -15,11 +15,22 @@
681 <allow interface="canonical.launchpad.interfaces.IBinaryAndSourcePackageName" />
682 </class>
683
684- <utility
685+ <class class="canonical.launchpad.database.binaryandsourcepackagename.BinaryAndSourcePackageNameIterator">
686+ <allow interface="canonical.launchpad.webapp.vocabulary.ICountableIterator" />
687+ </class>
688+
689+ <securedutility
690 name="BinaryAndSourcePackageName"
691 component="canonical.launchpad.database.binaryandsourcepackagename.BinaryAndSourcePackageNameVocabulary"
692 provides="zope.schema.interfaces.IVocabularyFactory"
693- />
694+ >
695+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
696+ </securedutility>
697+
698+ <class class="canonical.launchpad.database.binaryandsourcepackagename.BinaryAndSourcePackageNameVocabulary">
699+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
700+ </class>
701+
702
703 </facet>
704 </configure>
705
706=== modified file 'lib/lp/answers/configure.zcml'
707--- lib/lp/answers/configure.zcml 2009-09-22 18:45:02 +0000
708+++ lib/lp/answers/configure.zcml 2010-01-18 21:51:20 +0000
709@@ -221,11 +221,18 @@
710 <allow interface=".interfaces.faq.IFAQSet" />
711 </securedutility>
712
713- <utility
714+ <securedutility
715 name="FAQ"
716 component=".vocabulary.FAQVocabulary"
717 provides="zope.schema.interfaces.IVocabularyFactory"
718- />
719+ >
720+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
721+ </securedutility>
722+
723+ <class class=".vocabulary.FAQVocabulary">
724+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
725+ </class>
726+
727
728 <lp:help-folder
729 folder="help" type="canonical.launchpad.layers.AnswersLayer" />
730
731=== modified file 'lib/lp/answers/doc/faq-vocabulary.txt'
732--- lib/lp/answers/doc/faq-vocabulary.txt 2009-04-17 10:32:16 +0000
733+++ lib/lp/answers/doc/faq-vocabulary.txt 2010-01-18 21:51:20 +0000
734@@ -73,9 +73,10 @@
735 The searchForTerms() method returns a CountableIterator of terms that
736 are similar to the query:
737
738+ >>> from zope.security import proxy
739 >>> from canonical.launchpad.webapp.vocabulary import CountableIterator
740 >>> terms = vocabulary.searchForTerms('Problem showing SVG')
741- >>> isinstance(terms, CountableIterator)
742+ >>> proxy.isinstance(terms, CountableIterator)
743 True
744 >>> terms.count()
745 2
746
747=== modified file 'lib/lp/registry/doc/vocabularies.txt'
748--- lib/lp/registry/doc/vocabularies.txt 2009-12-24 01:41:54 +0000
749+++ lib/lp/registry/doc/vocabularies.txt 2010-01-18 21:51:20 +0000
750@@ -11,8 +11,12 @@
751 >>> launchbag.clear()
752
753 >>> from zope.schema.vocabulary import getVocabularyRegistry
754+ >>> from zope.security.proxy import removeSecurityProxy
755 >>> vocabulary_registry = getVocabularyRegistry()
756- >>> product_vocabulary = vocabulary_registry.get(None, "Product")
757+ >>> def get_naked_vocab(context, name):
758+ ... return removeSecurityProxy(
759+ ... vocabulary_registry.get(context, name))
760+ >>> product_vocabulary = get_naked_vocab(None, "Product")
761
762
763 == ActiveMailingList ==
764@@ -20,7 +24,7 @@
765 The active mailing lists vocabulary matches and returns only those mailing
766 lists which are active.
767
768- >>> list_vocabulary = vocabulary_registry.get(None, 'ActiveMailingList')
769+ >>> list_vocabulary = get_naked_vocab(None, 'ActiveMailingList')
770 >>> from canonical.launchpad.webapp.testing import verifyObject
771 >>> from canonical.launchpad.webapp.vocabulary import IHugeVocabulary
772 >>> verifyObject(IHugeVocabulary, list_vocabulary)
773@@ -181,7 +185,7 @@
774 Reflects the available distribution series. Results are ordered by
775 `name`
776
777- >>> distroseries_vocabulary = vocabulary_registry.get(
778+ >>> distroseries_vocabulary = get_naked_vocab(
779 ... None,"DistroSeries")
780 >>> for term in distroseries_vocabulary:
781 ... print "%30s %s" % (term.token, term.title)
782@@ -225,7 +229,7 @@
783 All the teams the person is an active member of.
784
785 >>> foo_bar = person_set.getByEmail('foo.bar@canonical.com')
786- >>> person_active_membership = vocabulary_registry.get(
787+ >>> person_active_membership = get_naked_vocab(
788 ... foo_bar, 'PersonActiveMembership')
789 >>> len(person_active_membership)
790 10
791@@ -320,7 +324,7 @@
792 [u'hwdb-team', u'landscape-developers', u'launchpad-users', u'name18',
793 u'name20']
794
795- >>> sample_person_teams_vocabulary = vocabulary_registry.get(
796+ >>> sample_person_teams_vocabulary = get_naked_vocab(
797 ... sample_person, 'PersonTeamParticipations')
798
799 >>> for term in sample_person_teams_vocabulary:
800@@ -343,13 +347,13 @@
801 to the current context. If no context is given, or if the context does
802 not have any milestones, a MilestoneVocabulary is empty...
803
804- >>> milestones = vocabulary_registry.get(None, 'Milestone')
805+ >>> milestones = get_naked_vocab(None, 'Milestone')
806 >>> len(milestones)
807 0
808
809 >>> from canonical.launchpad.interfaces import IMaloneApplication
810 >>> malone = getUtility(IMaloneApplication)
811- >>> milestones = vocabulary_registry.get(malone, 'Milestone')
812+ >>> milestones = get_naked_vocab(malone, 'Milestone')
813 >>> len(milestones)
814 0
815
816@@ -358,7 +362,7 @@
817 milestones from RelevantMilestonesMixin.getMilestoneWidgetValues()
818 but we need the big default vocabulary for form input validation.
819
820- >>> all_milestones = vocabulary_registry.get(sample_person, 'Milestone')
821+ >>> all_milestones = get_naked_vocab(sample_person, 'Milestone')
822 >>> len(all_milestones)
823 3
824 >>> for term in all_milestones:
825@@ -371,7 +375,7 @@
826 vocabulary.
827
828 >>> firefox = product_set.getByName('firefox')
829- >>> firefox_milestones = vocabulary_registry.get(firefox, 'Milestone')
830+ >>> firefox_milestones = get_naked_vocab(firefox, 'Milestone')
831 >>> for term in firefox_milestones:
832 ... print "%s: %s" % (term.value.target.name, term.value.name)
833 firefox: 1.0
834@@ -382,7 +386,7 @@
835 >>> firefox_trunk = firefox.getSeries('trunk')
836 >>> firefox_milestone = factory.makeMilestone(
837 ... product=firefox, name='firefox-milestone-no-series')
838- >>> firefox_trunk_milestones = vocabulary_registry.get(firefox_trunk,
839+ >>> firefox_trunk_milestones = get_naked_vocab(firefox_trunk,
840 ... 'Milestone')
841 >>> for term in firefox_trunk_milestones:
842 ... print "%s: %s" % (term.value.target.name, term.value.name)
843@@ -397,7 +401,7 @@
844 >>> firefox_task = bug_one.bugtasks[0]
845 >>> firefox_task.bugtargetdisplayname
846 u'Mozilla Firefox'
847- >>> firefox_task_milestones = vocabulary_registry.get(
848+ >>> firefox_task_milestones = get_naked_vocab(
849 ... firefox_task, 'Milestone')
850 >>> for term in firefox_task_milestones:
851 ... print "%s: %s" % (term.value.target.name, term.value.name)
852@@ -408,7 +412,7 @@
853 >>> debian_woody_task = bug_two.bugtasks[-1]
854 >>> debian_woody_task.bugtargetdisplayname
855 u'mozilla-firefox (Debian Woody)'
856- >>> debian_woody_milestones = vocabulary_registry.get(
857+ >>> debian_woody_milestones = get_naked_vocab(
858 ... debian_woody_task, 'Milestone')
859 >>> debian_woody = debian_woody_task.distroseries
860 >>> len(debian_woody_milestones)
861@@ -420,7 +424,7 @@
862 >>> milestone = debian_woody.milestones[0]
863 >>> milestone.active = False
864 >>> flush_database_updates()
865- >>> len(vocabulary_registry.get(debian_woody_task, 'Milestone'))
866+ >>> len(get_naked_vocab(debian_woody_task, 'Milestone'))
867 1
868
869 If the milestone was used in a bugtask before it was marked inactive, though,
870@@ -428,7 +432,7 @@
871
872 >>> debian_woody_task.milestone = milestone
873 >>> flush_database_updates()
874- >>> len(vocabulary_registry.get(debian_woody_task, 'Milestone'))
875+ >>> len(get_naked_vocab(debian_woody_task, 'Milestone'))
876 2
877
878 This is true for inactive milestones used in bugtasks for products and
879@@ -436,7 +440,7 @@
880
881 >>> product_bugtask = factory.makeBugTask(target=firefox)
882 >>> product_bugtask.milestone = firefox_milestone
883- >>> product_target_milestones = vocabulary_registry.get(
884+ >>> product_target_milestones = get_naked_vocab(
885 ... product_bugtask, 'Milestone')
886 >>> for term in product_target_milestones:
887 ... print "%s: %s" % (term.value.target.name, term.value.name)
888@@ -444,7 +448,7 @@
889 firefox: firefox-milestone-no-series
890
891 >>> firefox_milestone.active = False
892- >>> product_target_milestones = vocabulary_registry.get(
893+ >>> product_target_milestones = get_naked_vocab(
894 ... product_bugtask, 'Milestone')
895 >>> for term in product_target_milestones:
896 ... print "%s: %s" % (term.value.target.name, term.value.name)
897@@ -453,7 +457,7 @@
898
899 >>> productseries_bugtask = factory.makeBugTask(target=firefox_trunk)
900 >>> productseries_bugtask.milestone = firefox_milestone
901- >>> productseries_target_milestones = vocabulary_registry.get(
902+ >>> productseries_target_milestones = get_naked_vocab(
903 ... productseries_bugtask, 'Milestone')
904 >>> for term in productseries_target_milestones:
905 ... print "%s: %s" % (term.value.target.name, term.value.name)
906@@ -464,7 +468,7 @@
907 target are in the vocabulary.
908
909 >>> canvas_spec = firefox.getSpecification('canvas')
910- >>> spec_target_milestones = vocabulary_registry.get(
911+ >>> spec_target_milestones = get_naked_vocab(
912 ... canvas_spec, 'Milestone')
913 >>> for term in spec_target_milestones:
914 ... print "%s: %s" % (term.value.target.name, term.value.name)
915@@ -481,10 +485,10 @@
916 u'1.0'
917 >>> one_dot_o.active = False
918
919- >>> firefox_milestones = vocabulary_registry.get(firefox, 'Milestone')
920+ >>> firefox_milestones = get_naked_vocab(firefox, 'Milestone')
921 >>> len(firefox_milestones)
922 0
923- >>> firefox_task_milestones = vocabulary_registry.get(
924+ >>> firefox_task_milestones = get_naked_vocab(
925 ... firefox_task, 'Milestone')
926 >>> len(firefox_task_milestones)
927 0
928@@ -495,7 +499,7 @@
929 All the products in a project.
930
931 >>> mozilla_project = getUtility(IProjectSet).getByName('mozilla')
932- >>> mozilla_products_vocabulary = vocabulary_registry.get(
933+ >>> mozilla_products_vocabulary = get_naked_vocab(
934 ... mozilla_project,'ProjectProducts')
935
936 >>> for term in mozilla_products_vocabulary:
937@@ -508,7 +512,7 @@
938
939 The list of selectable projects. The results are ordered by displayname.
940
941- >>> project_vocabulary = vocabulary_registry.get(None, "Project")
942+ >>> project_vocabulary = get_naked_vocab(None, "Project")
943 >>> project_vocabulary.displayname
944 'Select a project group'
945
946@@ -542,7 +546,7 @@
947
948 The list of selectable products. Results are ordered by displayname.
949
950- >>> product_vocabulary = vocabulary_registry.get(None, "Product")
951+ >>> product_vocabulary = get_naked_vocab(None, "Product")
952 >>> product_vocabulary.displayname
953 'Select a project'
954
955@@ -583,8 +587,7 @@
956
957 The list of selectable products releases.
958
959- >>> productrelease_vocabulary = vocabulary_registry.get(None,
960- ... "ProductRelease")
961+ >>> productrelease_vocabulary = get_naked_vocab(None, "ProductRelease")
962 >>> productrelease_vocabulary.displayname
963 'Select a Product Release'
964
965@@ -603,7 +606,7 @@
966 All non-merged people with at least one email address. This vocabulary is
967 meant to be used only in the people merge form.
968
969- >>> vocab = vocabulary_registry.get(None, "PersonAccountToMerge")
970+ >>> vocab = get_naked_vocab(None, "PersonAccountToMerge")
971 >>> vocab.displayname
972 'Select a Person to Merge'
973
974@@ -668,7 +671,6 @@
975 True
976
977 # Here we cheat because IPerson.merged is a readonly attribute.
978- >>> from zope.security.proxy import removeSecurityProxy
979 >>> naked_cprov = removeSecurityProxy(cprov)
980 >>> naked_cprov.merged = 1
981 >>> naked_cprov.syncUpdate()
982@@ -693,7 +695,7 @@
983
984 The set of non-merged people.
985
986- >>> vocab = vocabulary_registry.get(None, "AdminMergeablePerson")
987+ >>> vocab = get_naked_vocab(None, "AdminMergeablePerson")
988 >>> vocab.displayname
989 'Select a Person to Merge'
990
991@@ -712,7 +714,7 @@
992
993 All non-merged people and teams.
994
995- >>> vocab = vocabulary_registry.get(None, "NonMergedPeopleAndTeams")
996+ >>> vocab = get_naked_vocab(None, "NonMergedPeopleAndTeams")
997 >>> vocab.displayname
998 'Select a Person or Team'
999
1000@@ -746,7 +748,7 @@
1001 None). It also includes all public teams and private teams the
1002 user has permission to view.
1003
1004- >>> vocab = vocabulary_registry.get(None, "ValidPersonOrTeam")
1005+ >>> vocab = get_naked_vocab(None, "ValidPersonOrTeam")
1006 >>> vocab.displayname
1007 'Select a Person or Team'
1008
1009@@ -794,7 +796,7 @@
1010 A PRIVATE team is displayed when the logged in user is a member of the team.
1011
1012 >>> commercial = person_set.getByEmail('commercial-member@canonical.com')
1013- >>> vocab = vocabulary_registry.get(commercial, "ValidPersonOrTeam")
1014+ >>> vocab = get_naked_vocab(commercial, "ValidPersonOrTeam")
1015 >>> login('commercial-member@canonical.com')
1016 >>> priv_team = factory.makeTeam(
1017 ... name='private-team',
1018@@ -861,7 +863,7 @@
1019 one of its email addresses.
1020
1021 >>> login('foo.bar@canonical.com')
1022- >>> vocab = vocabulary_registry.get(None, "ValidPersonOrTeam")
1023+ >>> vocab = get_naked_vocab(None, "ValidPersonOrTeam")
1024 >>> sorted(person.name for person in vocab.search('support'))
1025 [u'ubuntu-team']
1026
1027@@ -932,7 +934,7 @@
1028 All valid persons and teams are also valid owners.
1029
1030 >>> login(ANONYMOUS)
1031- >>> vocab = vocabulary_registry.get(None, "ValidOwner")
1032+ >>> vocab = get_naked_vocab(None, "ValidOwner")
1033 >>> vocab.displayname
1034 'Select a Person or Team'
1035
1036@@ -955,7 +957,7 @@
1037 except that its terms are limited only to teams. No non-team Persons will be
1038 returned.
1039
1040- >>> vocab = vocabulary_registry.get(None, 'ValidTeam')
1041+ >>> vocab = get_naked_vocab(None, 'ValidTeam')
1042 >>> vocab.displayname
1043 'Select a Team'
1044 >>> sorted((team.displayname, team.teamowner.displayname)
1045@@ -1062,21 +1064,21 @@
1046
1047 ValidTeamMember needs a context:
1048
1049- >>> vocab = vocabulary_registry.get(None, "ValidTeamMember")
1050+ >>> vocab = get_naked_vocab(None, "ValidTeamMember")
1051 Traceback (most recent call last):
1052 ...
1053 AssertionError: ...
1054
1055 ValidTeamMember's context must implement ITeam:
1056
1057- >>> vocab = vocabulary_registry.get(person, "ValidTeamMember")
1058+ >>> vocab = get_naked_vocab(person, "ValidTeamMember")
1059 Traceback (most recent call last):
1060 ...
1061 AssertionError: ...
1062
1063 'name16' is a valid member for 'ubuntu-team':
1064
1065- >>> vocab = vocabulary_registry.get(team, "ValidTeamMember")
1066+ >>> vocab = get_naked_vocab(team, "ValidTeamMember")
1067 >>> vocab.displayname
1068 'Select a Person or Team'
1069
1070@@ -1108,25 +1110,25 @@
1071
1072 ValidTeamOwner needs a context.
1073
1074- >>> vocab = vocabulary_registry.get(None, "ValidTeamOwner")
1075+ >>> vocab = get_naked_vocab(None, "ValidTeamOwner")
1076 Traceback (most recent call last):
1077 ...
1078 AssertionError: ...
1079
1080 ValidTeamOwner's context must provide IPerson or IPersonSet.
1081
1082- >>> vocabulary_registry.get(team, "ValidTeamOwner")
1083- <...ValidTeamOwnerVocabulary...
1084- >>> vocabulary_registry.get(person_set, "ValidTeamOwner")
1085- <...ValidTeamOwnerVocabulary...
1086- >>> vocabulary_registry.get(firefox, "ValidTeamOwner")
1087+ >>> get_naked_vocab(team, "ValidTeamOwner")
1088+ <...ValidTeamOwnerVocabulary...
1089+ >>> get_naked_vocab(person_set, "ValidTeamOwner")
1090+ <...ValidTeamOwnerVocabulary...
1091+ >>> get_naked_vocab(firefox, "ValidTeamOwner")
1092 Traceback (most recent call last):
1093 ...
1094 AssertionError: ...
1095
1096 'ubuntu-team' is not a valid owner for itself.
1097
1098- >>> vocab = vocabulary_registry.get(team, "ValidTeamOwner")
1099+ >>> vocab = get_naked_vocab(team, "ValidTeamOwner")
1100 >>> vocab.displayname
1101 'Select a Person or Team'
1102
1103@@ -1147,7 +1149,7 @@
1104
1105 All 'valid' persons who are not a team.
1106
1107- >>> vocab = vocabulary_registry.get(None, "ValidPerson")
1108+ >>> vocab = get_naked_vocab(None, "ValidPerson")
1109 >>> vocab.displayname
1110 'Select a Person'
1111 >>> people = vocab.search(None)
1112@@ -1172,8 +1174,7 @@
1113 >>> carlos = getUtility(IPersonSet).getByName('carlos')
1114 >>> carlos_team = factory.makeTeam(
1115 ... owner=carlos, name='carlos-team')
1116- >>> person_or_team_vocab = vocabulary_registry.get(
1117- ... None, "ValidPersonOrTeam")
1118+ >>> person_or_team_vocab = get_naked_vocab(None, "ValidPersonOrTeam")
1119 >>> carlos_people_or_team = person_or_team_vocab.search('carlos')
1120 >>> # The people or team search yields our one Carlos person and
1121 >>> # the new team.
1122@@ -1196,7 +1197,7 @@
1123 All products and distributions. Note that the value type is
1124 heterogeneous.
1125
1126- >>> vocab = vocabulary_registry.get(None, "DistributionOrProduct")
1127+ >>> vocab = get_naked_vocab(None, "DistributionOrProduct")
1128 >>> for term in vocab:
1129 ... if 'Ubuntu' in term.title:
1130 ... print term.title, '- class', term.value.__class__.__name__
1131@@ -1236,12 +1237,12 @@
1132 True
1133 >>> tomcat.active = False
1134 >>> flush_database_updates()
1135- >>> vocab = vocabulary_registry.get(None, "DistributionOrProduct")
1136+ >>> vocab = get_naked_vocab(None, "DistributionOrProduct")
1137 >>> tomcat in vocab
1138 False
1139 >>> tomcat.active = True
1140 >>> flush_database_updates()
1141- >>> vocab = vocabulary_registry.get(None, "DistributionOrProduct")
1142+ >>> vocab = get_naked_vocab(None, "DistributionOrProduct")
1143 >>> tomcat in vocab
1144 True
1145
1146@@ -1257,7 +1258,7 @@
1147 All products, projects and distributions. Note that the value type is
1148 heterogeneous.
1149
1150- >>> vocab = vocabulary_registry.get(None, "DistributionOrProductOrProject")
1151+ >>> vocab = get_naked_vocab(None, "DistributionOrProductOrProject")
1152 >>> for term in vocab:
1153 ... if 'Ubuntu' in term.title:
1154 ... print term.title, '- class', term.value.__class__.__name__
1155@@ -1297,7 +1298,7 @@
1156 >>> apache in vocab
1157 False
1158
1159- >>> vocab = vocabulary_registry.get(None, "DistributionOrProductOrProject")
1160+ >>> vocab = get_naked_vocab(None, "DistributionOrProductOrProject")
1161 >>> for term in vocab:
1162 ... if 'Apache' in term.title:
1163 ... print term.title, '- class', term.value.__class__.__name__
1164@@ -1307,7 +1308,7 @@
1165 >>> product_set.getByName('tomcat').active = True
1166 >>> getUtility(IProjectSet).getByName('apache').active = True
1167 >>> flush_database_updates()
1168- >>> vocab = vocabulary_registry.get(None, "DistributionOrProductOrProject")
1169+ >>> vocab = get_naked_vocab(None, "DistributionOrProductOrProject")
1170 >>> for term in vocab:
1171 ... if 'Apache' in term.title:
1172 ... print term.title, '- class', term.value.__class__.__name__
1173@@ -1325,7 +1326,7 @@
1174 DistributionOrProductOrProjectVocabulary (defined using the
1175 _clauseTables).
1176
1177- >>> featured_project_vocabulary = vocabulary_registry.get(
1178+ >>> featured_project_vocabulary = get_naked_vocab(
1179 ... None, 'FeaturedProject')
1180 >>> len(featured_project_vocabulary)
1181 9
1182@@ -1376,7 +1377,7 @@
1183 >>> check_permission('launchpad.Commercial', bac)
1184 False
1185
1186- >>> comm_proj_vocab = vocabulary_registry.get(bac, "CommercialProjects")
1187+ >>> comm_proj_vocab = get_naked_vocab(bac, "CommercialProjects")
1188 >>> print comm_proj_vocab.displayname
1189 Select a commercial project
1190
1191@@ -1404,7 +1405,7 @@
1192 >>> check_permission('launchpad.ProjectReview', product_set)
1193 True
1194
1195- >>> comm_proj_vocab = vocabulary_registry.get(registry_member, "CommercialProjects")
1196+ >>> comm_proj_vocab = get_naked_vocab(registry_member, "CommercialProjects")
1197 >>> print comm_proj_vocab.displayname
1198 Select a commercial project
1199
1200
1201=== modified file 'lib/lp/registry/vocabularies.zcml'
1202--- lib/lp/registry/vocabularies.zcml 2009-07-29 03:29:24 +0000
1203+++ lib/lp/registry/vocabularies.zcml 2010-01-18 21:51:20 +0000
1204@@ -3,195 +3,404 @@
1205 -->
1206
1207 <configure xmlns="http://namespaces.zope.org/zope">
1208- <utility
1209+ <securedutility
1210 name="Distribution"
1211 component="lp.registry.vocabularies.DistributionVocabulary"
1212 provides="zope.schema.interfaces.IVocabularyFactory"
1213- />
1214-
1215- <utility
1216+ >
1217+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
1218+ </securedutility>
1219+
1220+ <class class="lp.registry.vocabularies.DistributionVocabulary">
1221+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
1222+ </class>
1223+
1224+
1225+ <securedutility
1226 name="DistroSeries"
1227 component="lp.registry.vocabularies.DistroSeriesVocabulary"
1228 provides="zope.schema.interfaces.IVocabularyFactory"
1229- />
1230-
1231- <utility
1232+ >
1233+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
1234+ </securedutility>
1235+
1236+ <class class="lp.registry.vocabularies.DistroSeriesVocabulary">
1237+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
1238+ </class>
1239+
1240+
1241+ <securedutility
1242 name="FeaturedProject"
1243 component="lp.registry.vocabularies.FeaturedProjectVocabulary"
1244 provides="zope.schema.interfaces.IVocabularyFactory"
1245- />
1246-
1247- <utility
1248+ >
1249+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
1250+ </securedutility>
1251+
1252+ <class class="lp.registry.vocabularies.FeaturedProjectVocabulary">
1253+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
1254+ </class>
1255+
1256+
1257+ <securedutility
1258 name="FilteredDistroSeries"
1259 component="lp.registry.vocabularies.FilteredDistroSeriesVocabulary"
1260 provides="zope.schema.interfaces.IVocabularyFactory"
1261- />
1262-
1263- <utility
1264+ >
1265+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
1266+ </securedutility>
1267+
1268+ <class class="lp.registry.vocabularies.FilteredDistroSeriesVocabulary">
1269+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
1270+ </class>
1271+
1272+
1273+ <securedutility
1274 name="FilteredProductSeries"
1275 component="lp.registry.vocabularies.FilteredProductSeriesVocabulary"
1276 provides="zope.schema.interfaces.IVocabularyFactory"
1277- />
1278-
1279- <utility
1280+ >
1281+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
1282+ </securedutility>
1283+
1284+ <class class="lp.registry.vocabularies.FilteredProductSeriesVocabulary">
1285+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
1286+ </class>
1287+
1288+
1289+ <securedutility
1290 name="KarmaCategory"
1291 component="lp.registry.vocabularies.KarmaCategoryVocabulary"
1292 provides="zope.schema.interfaces.IVocabularyFactory"
1293- />
1294-
1295- <utility
1296+ >
1297+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
1298+ </securedutility>
1299+
1300+ <class class="lp.registry.vocabularies.KarmaCategoryVocabulary">
1301+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
1302+ </class>
1303+
1304+
1305+ <securedutility
1306 name="Milestone"
1307 component="lp.registry.vocabularies.MilestoneVocabulary"
1308 provides="zope.schema.interfaces.IVocabularyFactory"
1309- />
1310-
1311- <utility
1312+ >
1313+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
1314+ </securedutility>
1315+
1316+ <class class="lp.registry.vocabularies.MilestoneVocabulary">
1317+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
1318+ </class>
1319+
1320+
1321+ <securedutility
1322 name="NonMergedPeopleAndTeams"
1323 component="lp.registry.vocabularies.NonMergedPeopleAndTeamsVocabulary"
1324 provides="zope.schema.interfaces.IVocabularyFactory"
1325- />
1326-
1327- <utility
1328+ >
1329+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
1330+ </securedutility>
1331+
1332+ <class class="lp.registry.vocabularies.NonMergedPeopleAndTeamsVocabulary">
1333+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
1334+ </class>
1335+
1336+
1337+ <securedutility
1338 name="AdminMergeablePerson"
1339 component="lp.registry.vocabularies.AdminMergeablePersonVocabulary"
1340 provides="zope.schema.interfaces.IVocabularyFactory"
1341- />
1342-
1343- <utility
1344+ >
1345+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
1346+ </securedutility>
1347+
1348+ <class class="lp.registry.vocabularies.AdminMergeablePersonVocabulary">
1349+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
1350+ </class>
1351+
1352+
1353+ <securedutility
1354 name="PersonAccountToMerge"
1355 component="lp.registry.vocabularies.PersonAccountToMergeVocabulary"
1356 provides="zope.schema.interfaces.IVocabularyFactory"
1357- />
1358-
1359- <utility
1360+ >
1361+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
1362+ </securedutility>
1363+
1364+ <class class="lp.registry.vocabularies.PersonAccountToMergeVocabulary">
1365+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
1366+ </class>
1367+
1368+
1369+ <securedutility
1370 name="PersonActiveMembership"
1371 component="lp.registry.vocabularies.PersonActiveMembershipVocabulary"
1372 provides="zope.schema.interfaces.IVocabularyFactory"
1373- />
1374-
1375- <utility
1376+ >
1377+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
1378+ </securedutility>
1379+
1380+ <class class="lp.registry.vocabularies.PersonActiveMembershipVocabulary">
1381+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
1382+ </class>
1383+
1384+
1385+ <securedutility
1386 name="PersonTeamParticipations"
1387 component="lp.registry.vocabularies.person_team_participations_vocabulary_factory"
1388 provides="zope.schema.interfaces.IVocabularyFactory"
1389- />
1390-
1391- <utility
1392+ >
1393+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
1394+ </securedutility>
1395+
1396+
1397+ <securedutility
1398 name="Product"
1399 component="lp.registry.vocabularies.ProductVocabulary"
1400 provides="zope.schema.interfaces.IVocabularyFactory"
1401- />
1402-
1403- <utility
1404+ >
1405+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
1406+ </securedutility>
1407+
1408+ <class class="lp.registry.vocabularies.ProductVocabulary">
1409+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
1410+ </class>
1411+
1412+
1413+ <securedutility
1414 name="ProductRelease"
1415 component="lp.registry.vocabularies.ProductReleaseVocabulary"
1416 provides="zope.schema.interfaces.IVocabularyFactory"
1417- />
1418-
1419- <utility
1420+ >
1421+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
1422+ </securedutility>
1423+
1424+ <class class="lp.registry.vocabularies.ProductReleaseVocabulary">
1425+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
1426+ </class>
1427+
1428+
1429+ <securedutility
1430 name="ProductSeries"
1431 component="lp.registry.vocabularies.ProductSeriesVocabulary"
1432 provides="zope.schema.interfaces.IVocabularyFactory"
1433- />
1434-
1435- <utility
1436+ >
1437+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
1438+ </securedutility>
1439+
1440+ <class class="lp.registry.vocabularies.ProductSeriesVocabulary">
1441+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
1442+ </class>
1443+
1444+
1445+ <securedutility
1446 name="Project"
1447 component="lp.registry.vocabularies.ProjectVocabulary"
1448 provides="zope.schema.interfaces.IVocabularyFactory"
1449- />
1450-
1451- <utility
1452+ >
1453+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
1454+ </securedutility>
1455+
1456+ <class class="lp.registry.vocabularies.ProjectVocabulary">
1457+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
1458+ </class>
1459+
1460+
1461+ <securedutility
1462 name="ProjectProducts"
1463 component="lp.registry.vocabularies.project_products_vocabulary_factory"
1464 provides="zope.schema.interfaces.IVocabularyFactory"
1465- />
1466-
1467- <utility
1468+ >
1469+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
1470+ </securedutility>
1471+
1472+
1473+ <securedutility
1474 name="CommercialProjects"
1475 component="lp.registry.vocabularies.CommercialProjectsVocabulary"
1476 provides="zope.schema.interfaces.IVocabularyFactory"
1477- />
1478-
1479- <utility
1480+ >
1481+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
1482+ </securedutility>
1483+
1484+ <class class="lp.registry.vocabularies.CommercialProjectsVocabulary">
1485+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
1486+ </class>
1487+
1488+
1489+ <securedutility
1490 name="UserTeamsParticipation"
1491 component="lp.registry.vocabularies.UserTeamsParticipationVocabulary"
1492 provides="zope.schema.interfaces.IVocabularyFactory"
1493- />
1494-
1495- <utility
1496+ >
1497+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
1498+ </securedutility>
1499+
1500+ <class class="lp.registry.vocabularies.UserTeamsParticipationVocabulary">
1501+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
1502+ </class>
1503+
1504+
1505+ <securedutility
1506 name="UserTeamsParticipationPlusSelf"
1507 component="lp.registry.vocabularies.UserTeamsParticipationPlusSelfVocabulary"
1508 provides="zope.schema.interfaces.IVocabularyFactory"
1509- />
1510-
1511- <utility
1512+ >
1513+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
1514+ </securedutility>
1515+
1516+ <class class="lp.registry.vocabularies.UserTeamsParticipationPlusSelfVocabulary">
1517+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
1518+ </class>
1519+
1520+
1521+ <securedutility
1522 name="ActiveMailingList"
1523 component="lp.registry.vocabularies.ActiveMailingListVocabulary"
1524 provides="zope.schema.interfaces.IVocabularyFactory"
1525- />
1526-
1527- <utility
1528+ >
1529+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
1530+ </securedutility>
1531+
1532+ <class class="lp.registry.vocabularies.ActiveMailingListVocabulary">
1533+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
1534+ </class>
1535+
1536+
1537+ <securedutility
1538 name="ValidPersonOrTeam"
1539 component="lp.registry.vocabularies.ValidPersonOrTeamVocabulary"
1540 provides="zope.schema.interfaces.IVocabularyFactory"
1541- />
1542-
1543- <utility
1544+ >
1545+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
1546+ </securedutility>
1547+
1548+ <class class="lp.registry.vocabularies.ValidPersonOrTeamVocabulary">
1549+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
1550+ </class>
1551+
1552+
1553+ <securedutility
1554 name="ValidAssignee"
1555 component="lp.registry.vocabularies.ValidPersonOrTeamVocabulary"
1556 provides="zope.schema.interfaces.IVocabularyFactory"
1557- />
1558-
1559- <utility
1560+ >
1561+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
1562+ </securedutility>
1563+
1564+
1565+ <securedutility
1566 name="ValidMaintainer"
1567 component="lp.registry.vocabularies.ValidPersonOrTeamVocabulary"
1568 provides="zope.schema.interfaces.IVocabularyFactory"
1569- />
1570-
1571- <utility
1572+ >
1573+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
1574+ </securedutility>
1575+
1576+
1577+ <securedutility
1578 name="ValidOwner"
1579 component="lp.registry.vocabularies.ValidPersonOrTeamVocabulary"
1580 provides="zope.schema.interfaces.IVocabularyFactory"
1581- />
1582-
1583- <utility
1584+ >
1585+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
1586+ </securedutility>
1587+
1588+
1589+ <securedutility
1590 name="ValidTeam"
1591 component="lp.registry.vocabularies.ValidTeamVocabulary"
1592 provides="zope.schema.interfaces.IVocabularyFactory"
1593- />
1594-
1595- <utility
1596+ >
1597+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
1598+ </securedutility>
1599+
1600+ <class class="lp.registry.vocabularies.ValidTeamVocabulary">
1601+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
1602+ </class>
1603+
1604+
1605+ <securedutility
1606 name="ValidPerson"
1607 component="lp.registry.vocabularies.ValidPersonVocabulary"
1608 provides="zope.schema.interfaces.IVocabularyFactory"
1609- />
1610-
1611- <utility
1612+ >
1613+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
1614+ </securedutility>
1615+
1616+ <class class="lp.registry.vocabularies.ValidPersonVocabulary">
1617+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
1618+ </class>
1619+
1620+
1621+ <securedutility
1622 name="ValidTeamMember"
1623 component="lp.registry.vocabularies.ValidTeamMemberVocabulary"
1624 provides="zope.schema.interfaces.IVocabularyFactory"
1625- />
1626-
1627- <utility
1628+ >
1629+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
1630+ </securedutility>
1631+
1632+ <class class="lp.registry.vocabularies.ValidTeamMemberVocabulary">
1633+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
1634+ </class>
1635+
1636+
1637+ <securedutility
1638 name="ValidTeamOwner"
1639 component="lp.registry.vocabularies.ValidTeamOwnerVocabulary"
1640 provides="zope.schema.interfaces.IVocabularyFactory"
1641- />
1642-
1643- <utility
1644+ >
1645+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
1646+ </securedutility>
1647+
1648+ <class class="lp.registry.vocabularies.ValidTeamOwnerVocabulary">
1649+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
1650+ </class>
1651+
1652+
1653+ <securedutility
1654 name="DistributionOrProduct"
1655 component="lp.registry.vocabularies.DistributionOrProductVocabulary"
1656 provides="zope.schema.interfaces.IVocabularyFactory"
1657- />
1658-
1659- <utility
1660+ >
1661+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
1662+ </securedutility>
1663+
1664+ <class class="lp.registry.vocabularies.DistributionOrProductVocabulary">
1665+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
1666+ </class>
1667+
1668+
1669+ <securedutility
1670 name="DistributionOrProductOrProject"
1671 component="lp.registry.vocabularies.DistributionOrProductOrProjectVocabulary"
1672 provides="zope.schema.interfaces.IVocabularyFactory"
1673- />
1674-
1675- <utility
1676+ >
1677+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
1678+ </securedutility>
1679+
1680+ <class class="lp.registry.vocabularies.DistributionOrProductOrProjectVocabulary">
1681+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
1682+ </class>
1683+
1684+
1685+ <securedutility
1686 name="SourcePackageName"
1687 component="lp.registry.vocabularies.SourcePackageNameVocabulary"
1688 provides="zope.schema.interfaces.IVocabularyFactory"
1689- />
1690+ >
1691+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
1692+ </securedutility>
1693+
1694+ <class class="lp.registry.vocabularies.SourcePackageNameVocabulary">
1695+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
1696+ </class>
1697+
1698+
1699+ <class class="lp.registry.vocabularies.SourcePackageNameIterator">
1700+ <allow interface="canonical.launchpad.webapp.vocabulary.ICountableIterator"/>
1701+ </class>
1702+
1703 </configure>
1704
1705=== added file 'lib/lp/services/tests/test_vocabularies.py'
1706--- lib/lp/services/tests/test_vocabularies.py 1970-01-01 00:00:00 +0000
1707+++ lib/lp/services/tests/test_vocabularies.py 2010-01-18 21:51:20 +0000
1708@@ -0,0 +1,37 @@
1709+# Copyright 2010 Canonical Ltd. This software is licensed under the
1710+# GNU Affero General Public License version 3 (see the file LICENSE).
1711+
1712+"""Test registered vocabularies."""
1713+
1714+__metaclass__ = type
1715+__all__ = []
1716+
1717+import unittest
1718+
1719+from zope.component import getUtilitiesFor
1720+from zope.proxy import isProxy
1721+from zope.schema.interfaces import IVocabularyFactory
1722+from zope.security._proxy import _Proxy
1723+
1724+from canonical.testing.layers import FunctionalLayer
1725+from lp.testing import TestCase
1726+
1727+
1728+class TestVocabularies(TestCase):
1729+ layer = FunctionalLayer
1730+
1731+ def test_security_proxy(self):
1732+ """Our vocabularies should be registered with <securedutility>."""
1733+ vocabularies = getUtilitiesFor(IVocabularyFactory)
1734+ for name, vocab in vocabularies:
1735+ # If the vocabulary is not in a security proxy, check
1736+ # whether it is a vocabulary defined by zope, which are
1737+ # not registered with <securedutility> and can be ignored.
1738+ if not isProxy(vocab) and vocab.__module__[:5] != 'zope.':
1739+ raise AssertionError(
1740+ '%s.%s vocabulary is not wrapped in a security proxy.' % (
1741+ vocab.__module__, name))
1742+
1743+
1744+def test_suite():
1745+ return unittest.TestLoader().loadTestsFromName(__name__)
1746
1747=== modified file 'lib/lp/services/worlddata/vocabularies.zcml'
1748--- lib/lp/services/worlddata/vocabularies.zcml 2009-07-13 18:15:02 +0000
1749+++ lib/lp/services/worlddata/vocabularies.zcml 2010-01-18 21:51:20 +0000
1750@@ -3,9 +3,12 @@
1751 -->
1752
1753 <configure xmlns="http://namespaces.zope.org/zope">
1754- <utility
1755+ <securedutility
1756 name="TimezoneName"
1757 component="lp.services.worlddata.vocabularies.TimezoneNameVocabulary"
1758 provides="zope.schema.interfaces.IVocabularyFactory"
1759- />
1760+ >
1761+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
1762+ </securedutility>
1763+
1764 </configure>
1765
1766=== modified file 'lib/lp/soyuz/configure.zcml'
1767--- lib/lp/soyuz/configure.zcml 2010-01-14 03:39:27 +0000
1768+++ lib/lp/soyuz/configure.zcml 2010-01-18 21:51:20 +0000
1769@@ -260,10 +260,24 @@
1770 <allow
1771 interface="lp.soyuz.interfaces.binarypackagename.IBinaryPackageName"/>
1772 </class>
1773- <utility
1774+ <securedutility
1775 name="BinaryPackageName"
1776 component="lp.soyuz.model.binarypackagename.BinaryPackageNameVocabulary"
1777- provides="zope.schema.interfaces.IVocabularyFactory"/>
1778+ provides="zope.schema.interfaces.IVocabularyFactory">
1779+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
1780+ </securedutility>
1781+
1782+ <class class="lp.soyuz.model.binarypackagename.BinaryPackageNameVocabulary">
1783+ <allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
1784+ </class>
1785+
1786+ <!-- BinaryPackagenameIterator -->
1787+
1788+ <class
1789+ class="lp.soyuz.model.binarypackagename.BinaryPackageNameIterator">
1790+ <allow
1791+ interface="canonical.launchpad.webapp.vocabulary.ICountableIterator"/>
1792+ </class>
1793
1794 <!-- BinaryPackageNameSet -->
1795
1796
1797=== modified file 'lib/lp/soyuz/interfaces/binarypackagename.py'
1798--- lib/lp/soyuz/interfaces/binarypackagename.py 2009-06-25 04:06:00 +0000
1799+++ lib/lp/soyuz/interfaces/binarypackagename.py 2010-01-18 21:51:20 +0000
1800@@ -84,6 +84,7 @@
1801 to report a bug in.
1802 """
1803
1804+ id = Int(title=_('ID'), required=True, readonly=True)
1805+
1806 name = TextLine(title=_('Binary or Source package name'),
1807 required=True, constraint=name_validator)
1808-