Skip to content

Commit

Permalink
Fix ftests. The problem was that the forms were obviously trying to m…
Browse files Browse the repository at this point in the history
…odify

object's attributes.  Under Zope3's standard publication, this yields to 
ForbiddenAttribute errors due to the lack of security declarations.  So just
for the ftests I invented two directives and a grokker that allow us to
make security declarations in the model class.

Maybe this or something like this makes it into grokcore.security (and thereby
Grok itself) soon.
  • Loading branch information
philikon committed Aug 1, 2008
1 parent b37c873 commit c9ca9fd
Show file tree
Hide file tree
Showing 11 changed files with 116 additions and 14 deletions.
1 change: 1 addition & 0 deletions src/grokcore/formlib/ftesting.zcml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<include package="zope.app.zcmlfiles" file="meta.zcml" />
<include package="zope.securitypolicy" file="meta.zcml" />
<include package="grokcore.formlib" file="meta.zcml" />
<grok:grok package="grokcore.formlib.testing" />

<include package="zope.app.zcmlfiles" />
<include package="zope.securitypolicy" />
Expand Down
6 changes: 4 additions & 2 deletions src/grokcore/formlib/ftests/form/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,11 @@ class IMammoth(Interface):
name = schema.TextLine(title=u"Name")
size = schema.TextLine(title=u"Size", default=u"Quite normal")

class Mammoth(grok.Context):
class Mammoth(grok.testing.Model):
implements(IMammoth)

grok.testing.protect_get(grok.Public, 'name', 'size')
grok.testing.protect_set(grok.Public, 'name', 'size')

name = FieldProperty(IMammoth['name'])
size = FieldProperty(IMammoth['size'])

Expand Down
10 changes: 7 additions & 3 deletions src/grokcore/formlib/ftests/form/addform.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,20 @@
from zope import schema
from zope.interface import Interface, implements
from zope.app.container.btree import BTreeContainer
from zope.app.container.contained import Contained
from zope.app.container.interfaces import IContainer

class Zoo(BTreeContainer):
pass
class Zoo(grok.testing.Model, BTreeContainer):
grok.testing.protect_get(grok.Public, *IContainer)

class IMammoth(Interface):
name = schema.TextLine(title=u"Name")
size = schema.TextLine(title=u"Size", default=u"Quite normal")

class Mammoth(grok.Context):
class Mammoth(Contained, grok.testing.Model):
implements(IMammoth)
grok.testing.protect_get(grok.Public, 'name', 'size')
grok.testing.protect_set(grok.Public, 'name', 'size')

def __init__(self, name='', size=''):
self.name = name
Expand Down
9 changes: 6 additions & 3 deletions src/grokcore/formlib/ftests/form/addform_applydata.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,19 @@
from zope import schema, interface
from zope.lifecycleevent.interfaces import IObjectModifiedEvent
from zope.app.container.btree import BTreeContainer
from zope.app.container.interfaces import IContainer

class Zoo(BTreeContainer):
pass
class Zoo(grok.testing.Model, BTreeContainer):
grok.testing.protect_get(grok.Public, *IContainer)

class IMammoth(interface.Interface):
name = schema.TextLine(title=u"Name")
size = schema.TextLine(title=u"Size")

class Mammoth(grok.Context):
class Mammoth(grok.testing.Model):
grok.implements(IMammoth)
grok.testing.protect_get(grok.Public, 'name', 'size')
grok.testing.protect_set(grok.Public, 'name', 'size')

class Index(grok.View):
grok.context(Mammoth)
Expand Down
4 changes: 3 additions & 1 deletion src/grokcore/formlib/ftests/form/editform_applydata.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@
from zope import schema
from zope.lifecycleevent.interfaces import IObjectModifiedEvent

class Mammoth(grok.Context):
class Mammoth(grok.testing.Model):
grok.testing.protect_get(grok.Public, 'name', 'size')
grok.testing.protect_set(grok.Public, 'name', 'size')

def __init__(self, name='', size=''):
self._name = name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,10 @@ class IMammoth(interface.Interface):
name = schema.TextLine(title=u"Name")
size = schema.TextLine(title=u"Size")

class Mammoth(grok.Context):
class Mammoth(grok.testing.Model):
grok.implements(IMammoth)
grok.testing.protect_get(grok.Public, 'name', 'size')
grok.testing.protect_set(grok.Public, 'name', 'size')

def __init__(self, name='', size=''):
self._name = name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,10 @@ class IMammoth(Interface):
name = schema.TextLine(title=u"Name")
size = schema.TextLine(title=u"Size", default=u"Quite normal")

class Mammoth(grok.Context):
class Mammoth(grok.testing.Model):
implements(IMammoth)
grok.testing.protect_get(grok.Public, 'name', 'size')
grok.testing.protect_set(grok.Public, 'name', 'size')

class Edit(grok.EditForm):
pass
Expand Down
4 changes: 3 additions & 1 deletion src/grokcore/formlib/ftests/form/form.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,10 @@ class IMammoth(Interface):
name = schema.TextLine(title=u"Name")
size = schema.TextLine(title=u"Size", default=u"Quite normal")

class Mammoth(grok.Context):
class Mammoth(grok.testing.Model):
implements(IMammoth)
grok.testing.protect_get(grok.Public, 'name', 'size')
grok.testing.protect_set(grok.Public, 'name', 'size')

name = FieldProperty(IMammoth['name'])
size = FieldProperty(IMammoth['size'])
Expand Down
5 changes: 4 additions & 1 deletion src/grokcore/formlib/ftests/form/templateform.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@
import grokcore.formlib as grok
from zope import schema

class Mammoth(grok.Context):
class Mammoth(grok.testing.Model):
grok.testing.protect_get(grok.Public, 'name', 'size')
grok.testing.protect_set(grok.Public, 'name', 'size')

class fields:
name = schema.TextLine(title=u"Name")
size = schema.TextLine(title=u"Size", default=u"Quite normal")
Expand Down
4 changes: 3 additions & 1 deletion src/grokcore/formlib/ftests/form/update.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,10 @@
class IMammoth(Interface):
name = schema.TextLine(title=u"Name")

class Mammoth(grok.Context):
class Mammoth(grok.testing.Model):
implements(IMammoth)
grok.testing.protect_get(grok.Public, 'name', 'report')
grok.testing.protect_set(grok.Public, 'name', 'report')

name = u'Manfred'

Expand Down
79 changes: 79 additions & 0 deletions src/grokcore/formlib/testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,87 @@
##############################################################################
"""Grok test helpers
"""
import martian
from martian.error import GrokError
from zope.configuration.config import ConfigurationMachine

import grokcore.security
from grokcore.security.util import protect_getattr
from grokcore.security.util import protect_setattr
from grokcore.component import zcml
from grokcore.component import Context

# Below is a simple grokker + directives that allow you to protect
# attributes of a class with Zope 3 security checkers. This is needed
# to run the ftests of this package with the standard Zope publication.
# We may hope that something like this eventually makes it into
# grokcore.security.

class Model(Context):
pass


class protect_get(grokcore.security.require):
store = martian.MULTIPLE
default = []

def validate(self, permission, *attrs):
super(protect_get, self).validate(permission)
for name in attrs:
# TODO We should probably check whether 'name' is a valid
# Python identifier
martian.validateText(self, name)

def factory(self, permission, *attrs):
permission = super(protect_get, self).factory(permission)
return (permission, attrs)

# Override baseclass's __call__. This directive can't be used as
# a decorator at the same time like grok.require() can.
def __call__(self, *args, **kw):
raise NotImplementedError

class protect_set(protect_get):
pass

class ModelSecurityGrokker(martian.ClassGrokker):
martian.component(Model)
martian.directive(protect_get)
martian.directive(protect_set)

def execute(self, factory, config, protect_get, protect_set, **kw):
get_names = {}
for permission, attrs in protect_get:
for name in attrs:
if name in get_names:
raise GrokError("Duplicate read protection for %r "
"attribute on %r." % (name, factory),
factory)
get_names[name] = permission

set_names = {}
for permission, attrs in protect_set:
for name in attrs:
if name in set_names:
raise GrokError("Duplicate write protection for %r "
"attribute on %r." % (name, factory),
factory)
set_names[name] = permission

for name, permission in get_names.items():
config.action(
discriminator=('protectName', factory, name),
callable=protect_getattr,
args=(factory, name, permission),
)
for name, permission in set_names.items():
config.action(
discriminator=('protectSetAttribute', factory, name),
callable=protect_setattr,
args=(factory, name, permission),
)
return True


def grok(module_name):
config = ConfigurationMachine()
Expand Down

0 comments on commit c9ca9fd

Please sign in to comment.