Source code for grokcore.security.directive
##############################################################################
#
# Copyright (c) 2006-2007 Zope Foundation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Grok directives.
"""
import sys
import grokcore.component
import martian
from martian import util
from martian.directive import StoreMultipleTimes
from martian.error import GrokError
from martian.error import GrokImportError
from grokcore.security import components
class RequireDirectiveStore(StoreMultipleTimes):
def get(self, directive, component, default):
permissions = getattr(component, directive.dotted_name(), default)
if (permissions is default) or not permissions:
return default
if len(permissions) > 1:
raise GrokError(
'grok.require was called multiple times in '
'%r. It may only be set once for a class.'
% component, component)
return permissions[0]
def pop(self, locals_, directive):
return locals_[directive.dotted_name()].pop()
[docs]
class require(martian.Directive):
scope = martian.CLASS
store = RequireDirectiveStore()
def validate(self, value):
if util.check_subclass(value, components.Permission):
return
if util.not_unicode_or_ascii(value):
raise GrokImportError(
"You can only pass unicode, ASCII, or a subclass "
"of grok.Permission to the '%s' directive." % self.name)
def factory(self, value):
if util.check_subclass(value, components.Permission):
return grokcore.component.name.bind().get(value)
return value
def __call__(self, func):
# grok.require can be used both as a class-level directive and
# as a decorator for methods. Therefore we return a decorator
# here, which may be used for methods, or simply ignored when
# used as a directive.
frame = sys._getframe(1)
permission = self.store.pop(frame.f_locals, self)
self.set(func, [permission])
return func
[docs]
class permissions(martian.Directive):
"""The `grokcore.security.permissions()` directive.
This directive is used inside of a `grok.Role` subclass to list the
permissions which each member of the role should always possess.
Note that permissions should be passed as strings, and that several
permissions they can simply be supplied as multiple arguments; there
is no need to place them inside of a tuple or list::
class MyRole(grokcore.security.Role):
grokcore.security.permissions('page.CreatePage', 'page.EditPage')
...
"""
scope = martian.CLASS
store = martian.ONCE
default = []
def validate(self, *values):
for value in values:
if martian.util.check_subclass(value, components.Permission):
continue
if martian.util.not_unicode_or_ascii(value):
raise GrokImportError(
"You can only pass unicode values, ASCII values, or "
"subclasses of grok.Permission to the '%s' directive."
% self.name)
def factory(self, *values):
permission_ids = []
for value in values:
if martian.util.check_subclass(value, components.Permission):
permission_ids.append(
grokcore.component.name.bind().get(value))
else:
permission_ids.append(value)
return permission_ids