Beispiel #1
0
def viewletManagerDirective(
    _context, name, permission,
    for_=Interface, layer=IDefaultBrowserLayer, view=IBrowserView,
    provides=interfaces.IViewletManager, class_=None, template=None,
    allowed_interface=None, allowed_attributes=None):

    # If class is not given we use the basic viewlet manager.
    if class_ is None:
        class_ = manager.ViewletManagerBase

    # Iterate over permissions
    if allowed_attributes is None:
        allowed_attributes = ['render', 'update']
    if allowed_interface is not None:
        for interface in allowed_interface:
            allowed_attributes.extend(interface.names())

    # Make sure that the template exists and that all low-level API methods
    # have the right permission.
    if template:
        template = os.path.abspath(str(_context.path(template)))
        if not os.path.isfile(template):
            raise ConfigurationError("No such file", template)
        allowed_attributes.append('__getitem__')

        # Create a new class based on the template and class.
        new_class = manager.ViewletManager(
            name, provides, template=template, bases=(class_, ))
    else:
        # Create a new class based on the class.
        new_class = manager.ViewletManager(name, provides, bases=(class_, ))

    # Register interfaces
    _handle_for(_context, for_)
    zcml.interface(_context, view)

    # register a viewlet manager
    _context.action(
        discriminator = ('viewletManager', for_, layer, view, name),
        callable = zcml.handler,
        args = ('registerAdapter',
                new_class, (for_, layer, view), provides, name,
                _context.info),)
    _context.action(
        discriminator = ('five:protectClass', new_class),
        callable = protectClass,
        args = (new_class, permission)
        )
    if allowed_attributes:
        for attr in allowed_attributes:
            _context.action(
                discriminator = ('five:protectName', new_class, attr),
                callable = protectName,
                args = (new_class, attr, permission)
                )
    _context.action(
        discriminator = ('five:initialize:class', new_class),
        callable = InitializeClass,
        args = (new_class,)
        )
Beispiel #2
0
def pageletDirective(
    _context, class_, name, permission, for_=zope.interface.Interface,
    layer=IDefaultBrowserLayer, provides=interfaces.IPagelet,
    allowed_interface=None, allowed_attributes=None, **kwargs):

    # Security map dictionary
    required = {}

    # Get the permission; mainly to correctly handle CheckerPublic.
    permission = viewmeta._handle_permission(_context, permission)

    # The class must be specified.
    if not class_:
        raise ConfigurationError("Must specify a class.")

    if not zope.interface.interfaces.IInterface.providedBy(provides):
        raise ConfigurationError("Provides interface provide IInterface.")

    ifaces = list(zope.interface.Declaration(provides).flattened())
    if interfaces.IPagelet not in ifaces:
        raise ConfigurationError("Provides interface must inherit IPagelet.")

    # Build a new class that we can use different permission settings if we
    # use the class more then once.
    cdict = {}
    cdict['__name__'] = name
    cdict.update(kwargs)
    new_class = type(class_.__name__, (class_, browser.BrowserPagelet), cdict)

    # Set up permission mapping for various accessible attributes
    viewmeta._handle_allowed_interface(
        _context, allowed_interface, permission, required)
    viewmeta._handle_allowed_attributes(
        _context, allowed_attributes, permission, required)
    viewmeta._handle_allowed_attributes(
        _context, kwargs.keys(), permission, required)
    viewmeta._handle_allowed_attributes(
        _context, ('__call__', 'browserDefault', 'update', 'render',
                   'publishTraverse'), permission, required)

    # Register the interfaces.
    viewmeta._handle_for(_context, for_)

    # provide the custom provides interface if not allready provided
    if not provides.implementedBy(new_class):
        zope.interface.classImplements(new_class, provides)

    # Create the security checker for the new class
    zope.security.checker.defineChecker(new_class,
        zope.security.checker.Checker(required))

    # register pagelet
    _context.action(
        discriminator = ('pagelet', for_, layer, name),
        callable = zope.component.zcml.handler,
        args = ('registerAdapter',
                new_class, (for_, layer), provides, name, _context.info),)
Beispiel #3
0
def serviceDirective(
    _context,
    method,
    accept,
    factory,
    for_,
    permission,
    layer=IDefaultBrowserLayer,
    name=u"",
):

    _handle_for(_context, for_)

    media_types = parse_accept_header(accept)
    for media_type in media_types:
        service_id = register_service(method.upper(), media_type)
        view_name = service_id + name

        # We need a service for CORS preflight processing but we don't get the
        # desired Accept header in the preflight request. Thus we just register
        # the current service_id for the given method.
        register_method_for_preflight(method.upper(), service_id)

        # Create a new class. We'll execute some security declarations on it
        # and don't want to modify the original class.
        cdict = getSecurityInfo(factory)
        cdict["__name__"] = view_name
        cdict["method"] = method.upper()
        new_class = type(factory.__name__, (factory, BrowserView), cdict)

        _context.action(
            discriminator=("plone.rest:service", method, media_type, for_,
                           name, layer),
            callable=handler,
            args=(
                "registerAdapter",
                new_class,
                (for_, layer),
                Interface,
                view_name,
                _context.info,
            ),
        )

        _context.action(
            discriminator=("plone.rest:protectClass", new_class),
            callable=protectClass,
            args=(new_class, permission),
        )
        _context.action(
            discriminator=("plone.rest:InitializeClass", new_class),
            callable=InitializeClass,
            args=(new_class, ),
        )
Beispiel #4
0
def serviceDirective(
        _context,
        method,
        accept,
        factory,
        for_,
        permission,
        layer=IDefaultBrowserLayer,
        name=u'',
        ):

    _handle_for(_context, for_)

    media_types = parse_accept_header(accept)
    for media_type in media_types:
        service_id = register_service(method.upper(), media_type)
        view_name = service_id + name

        # We need a service for CORS preflight processing but we don't get the
        # desired Accept header in the preflight request. Thus we just register
        # the current service_id for the given method.
        register_method_for_preflight(method.upper(), service_id)

        # Create a new class. We'll execute some security declarations on it
        # and don't want to modify the original class.
        cdict = getSecurityInfo(factory)
        cdict['__name__'] = view_name
        cdict['method'] = method.upper()
        new_class = type(factory.__name__, (factory, BrowserView), cdict)

        _context.action(
            discriminator=('plone.rest:service', method, media_type, for_,
                           name, layer),
            callable=handler,
            args=('registerAdapter', new_class, (for_, layer), Interface,
                  view_name, _context.info),
        )

        _context.action(
            discriminator=('plone.rest:protectClass', new_class),
            callable=protectClass,
            args=(new_class, permission)
        )
        _context.action(
            discriminator=('plone.rest:InitializeClass', new_class),
            callable=InitializeClass,
            args=(new_class,)
            )
Beispiel #5
0
def cors_policy_directive(
    _context,
    allow_origin,
    allow_credentials,
    allow_methods=None,
    expose_headers=None,
    allow_headers=None,
    max_age=None,
    for_=Interface,
    layer=IDefaultBrowserLayer,
):

    _handle_for(_context, for_)

    # Create a new policy class and store the CORS policy configuration in
    # class attributes.
    cdict = {}
    cdict["allow_origin"] = [o.strip() for o in allow_origin.split(",")]
    if allow_methods is not None:
        cdict["allow_methods"] = [m.strip() for m in allow_methods.split(",")]
    else:
        cdict["allow_methods"] = None
    cdict["allow_credentials"] = allow_credentials
    if expose_headers:
        cdict["expose_headers"] = [
            h.strip() for h in expose_headers.split(",")
        ]
    else:
        cdict["expose_headers"] = []
    if allow_headers:
        cdict["allow_headers"] = [h.strip() for h in allow_headers.split(",")]
    else:
        cdict["allow_headers"] = []
    cdict["max_age"] = max_age
    new_class = type(CORSPolicy.__name__, (CORSPolicy, ), cdict)

    _context.action(
        discriminator=("plone.rest:CORSPolicy", for_, layer),
        callable=handler,
        args=(
            "registerAdapter",
            new_class,
            (for_, layer),
            ICORSPolicy,
            u"",
            _context.info,
        ),
    )
Beispiel #6
0
def cors_policy_directive(
        _context,
        allow_origin,
        allow_credentials,
        allow_methods=None,
        expose_headers=None,
        allow_headers=None,
        max_age=None,
        for_=Interface,
        layer=IDefaultBrowserLayer,):

    _handle_for(_context, for_)

    # Create a new policy class and store the CORS policy configuration in
    # class attributes.
    cdict = {}
    cdict['allow_origin'] = [o.strip() for o in allow_origin.split(',')]
    if allow_methods is not None:
        cdict['allow_methods'] = [m.strip() for m in allow_methods.split(',')]
    else:
        cdict['allow_methods'] = None
    cdict['allow_credentials'] = allow_credentials
    if expose_headers:
        cdict['expose_headers'] = [
            h.strip() for h in expose_headers.split(',')]
    else:
        cdict['expose_headers'] = []
    if allow_headers:
        cdict['allow_headers'] = [h.strip() for h in allow_headers.split(',')]
    else:
        cdict['allow_headers'] = []
    cdict['max_age'] = max_age
    new_class = type(CORSPolicy.__name__, (CORSPolicy,), cdict)

    _context.action(
        discriminator=('plone.rest:CORSPolicy', for_, layer),
        callable=handler,
        args=('registerAdapter', new_class, (for_, layer),
              ICORSPolicy, u'', _context.info),
        )
Beispiel #7
0
def viewletDirective(_context,
                     name,
                     permission,
                     for_=Interface,
                     layer=IDefaultBrowserLayer,
                     view=IBrowserView,
                     manager=interfaces.IViewletManager,
                     class_=None,
                     template=None,
                     attribute='render',
                     allowed_interface=None,
                     allowed_attributes=None,
                     **kwargs):

    # Either the class or template must be specified.
    if not (class_ or template):
        raise ConfigurationError("Must specify a class or template")

    # Make sure that all the non-default attribute specifications are correct.
    if attribute != 'render':
        if template:
            raise ConfigurationError(
                "Attribute and template cannot be used together.")

        # Note: The previous logic forbids this condition to evere occur.
        if not class_:
            raise ConfigurationError(
                "A class must be provided if attribute is used")

    # Iterate over permissions
    if allowed_attributes is None:
        allowed_attributes = ['render', 'update']
    if allowed_interface is not None:
        for interface in allowed_interface:
            allowed_attributes.extend(interface.names())

    # Make sure that the template exists and that all low-level API methods
    # have the right permission.
    if template:
        template = os.path.abspath(str(_context.path(template)))
        if not os.path.isfile(template):
            raise ConfigurationError("No such file", template)
        allowed_attributes.append('__getitem__')

    # Make sure the has the right form, if specified.
    if class_:
        if attribute != 'render':
            if not hasattr(class_, attribute):
                raise ConfigurationError(
                    "The provided class doesn't have the specified attribute.")
        if template:
            # Create a new class for the viewlet template and class.
            new_class = viewlet.SimpleViewletClass(template,
                                                   bases=(class_, ),
                                                   attributes=kwargs)
        else:
            if not hasattr(class_, 'browserDefault'):
                cdict = {
                    'browserDefault':
                    lambda self, request: (getattr(self, attribute), ())
                }
            else:
                cdict = {}

            cdict['__name__'] = name
            cdict['__page_attribute__'] = attribute
            cdict.update(kwargs)
            new_class = type(class_.__name__,
                             (class_, viewlet.SimpleAttributeViewlet), cdict)

    else:
        # Create a new class for the viewlet template alone.
        new_class = viewlet.SimpleViewletClass(template,
                                               name=name,
                                               attributes=kwargs)

    # Register the interfaces.
    _handle_for(_context, for_)
    zcml.interface(_context, view)

    # register viewlet
    _context.action(
        discriminator=('viewlet', for_, layer, view, manager, name),
        callable=zcml.handler,
        args=('registerAdapter', new_class, (for_, layer, view, manager),
              interfaces.IViewlet, name, _context.info),
    )
    _context.action(discriminator=('five:protectClass', new_class),
                    callable=protectClass,
                    args=(new_class, permission))
    if allowed_attributes:
        for attr in allowed_attributes:
            _context.action(discriminator=('five:protectName', new_class,
                                           attr),
                            callable=protectName,
                            args=(new_class, attr, permission))
    _context.action(discriminator=('five:initialize:class', new_class),
                    callable=InitializeClass,
                    args=(new_class, ))
Beispiel #8
0
def page(
    _context,
    name,
    permission,
    for_=Interface,
    layer=IDefaultBrowserLayer,
    template=None,
    class_=None,
    allowed_interface=None,
    allowed_attributes=None,
    attribute='__call__',
    menu=None,
    title=None,
):
    _handle_menu(_context, menu, title, [for_], name, permission, layer)
    required = {}

    permission = _handle_permission(_context, permission)

    if not (class_ or template):
        raise ConfigurationError("Must specify a class or template")

    if attribute != '__call__':
        if template:
            raise ConfigurationError(
                "Attribute and template cannot be used together.")

        if not class_:
            raise ConfigurationError(
                "A class must be provided if attribute is used")

    if template:
        template = os.path.abspath(str(_context.path(template)))
        if not os.path.isfile(template):
            raise ConfigurationError("No such file", template)

    # TODO: new __name__ attribute must be tested
    if class_:
        if attribute != '__call__':
            if not hasattr(class_, attribute):
                raise ConfigurationError(
                    "The provided class doesn't have the specified attribute ")
        if template:
            # class and template
            new_class = SimpleViewClass(template, bases=(class_, ), name=name)
        else:
            if not hasattr(class_, 'browserDefault'):
                cdict = {
                    'browserDefault':
                    lambda self, request: (getattr(self, attribute), ())
                }
            else:
                cdict = {}

            cdict['__name__'] = name
            cdict['__page_attribute__'] = attribute
            cdict.update(getSecurityInfo(class_))
            new_class = type(class_.__name__, (
                class_,
                simple,
            ), cdict)

            if attribute != "__call__":
                # in case the attribute does not provide a docstring,
                # ZPublisher refuses to publish it.  So, as a workaround,
                # we provide a stub docstring
                func = getattr(new_class, attribute)
                if not func.__doc__:
                    # cannot test for MethodType/UnboundMethod here
                    # because of ExtensionClass
                    if hasattr(func, 'im_func'):
                        # you can only set a docstring on functions, not
                        # on method objects
                        func = func.im_func
                    func.__doc__ = "Stub docstring to make ZPublisher work"

        if hasattr(class_, '__implements__'):
            classImplements(new_class, IBrowserPublisher)

    else:
        # template
        new_class = SimpleViewClass(template, name=name)

    for n in ('', attribute):
        required[n] = permission

    _handle_allowed_interface(_context, allowed_interface, permission,
                              required)
    _handle_allowed_attributes(_context, allowed_attributes, permission,
                               required)

    _handle_for(_context, for_)

    _configure_z2security(_context, new_class, required)

    _context.action(
        discriminator=('view', (for_, layer), name, IBrowserRequest),
        callable=handler,
        args=('registerAdapter', new_class, (for_, layer), Interface, name,
              _context.info),
    )
Beispiel #9
0
    def __call__(self):
        (_context, name, (for_, layer), permission, class_, allowed_interface,
         allowed_attributes) = self.args

        required = {}

        cdict = {}
        pages = {}

        for pname, attribute, template in self.pages:

            if template:
                cdict[pname] = ViewPageTemplateFile(template)
                if attribute and attribute != name:
                    cdict[attribute] = cdict[pname]
            else:
                if not hasattr(class_, attribute):
                    raise ConfigurationError("Undefined attribute", attribute)

            attribute = attribute or pname
            required[pname] = permission

            pages[pname] = attribute

        # This should go away, but noone seems to remember what to do. :-(
        if hasattr(class_, 'publishTraverse'):

            def publishTraverse(self,
                                request,
                                name,
                                pages=pages,
                                getattr=getattr):

                if name in pages:
                    return getattr(self, pages[name])
                view = queryMultiAdapter((self, request), name=name)
                if view is not None:
                    return view

                m = class_.publishTraverse.__get__(self)
                return m(request, name)

        else:

            def publishTraverse(self,
                                request,
                                name,
                                pages=pages,
                                getattr=getattr):

                if name in pages:
                    return getattr(self, pages[name])
                view = queryMultiAdapter((self, request), name=name)
                if view is not None:
                    return view

                raise NotFound(self, name, request)

        cdict['publishTraverse'] = publishTraverse

        if not hasattr(class_, 'browserDefault'):
            if self.default or self.pages:
                default = self.default or self.pages[0][0]
                cdict['browserDefault'] = (
                    lambda self, request, default=default: (self, (default, )))
            elif providesCallable(class_):
                cdict['browserDefault'] = (lambda self, request: (self, ()))

        if class_ is not None:
            cdict.update(getSecurityInfo(class_))
            bases = (class_, simple)
        else:
            bases = (simple, )

        try:
            cname = str(name)
        except:
            cname = "GeneratedClass"

        cdict['__name__'] = name
        newclass = type(cname, bases, cdict)

        for n in ('', ):
            required[n] = permission

        _handle_allowed_interface(_context, allowed_interface, permission,
                                  required)
        _handle_allowed_attributes(_context, allowed_attributes, permission,
                                   required)
        _handle_for(_context, for_)

        _configure_z2security(_context, newclass, required)

        if self.provides is not None:
            _context.action(discriminator=None,
                            callable=provideInterface,
                            args=('', self.provides))

        _context.action(
            discriminator=('view', (for_, layer), name, self.provides),
            callable=handler,
            args=('registerAdapter', newclass, (for_, layer), self.provides,
                  name, _context.info),
        )
def page(_context, name, permission, for_=Interface,
         layer=IDefaultBrowserLayer, template=None, class_=None,
         allowed_interface=None, allowed_attributes=None,
         attribute='__call__', menu=None, title=None, 
         ):
    name = str(name)  # De-unicode
    _handle_menu(_context, menu, title, [for_], name, permission, layer)
    required = {}

    permission = _handle_permission(_context, permission)

    if not (class_ or template):
        raise ConfigurationError("Must specify a class or template")

    if attribute != '__call__':
        if template:
            raise ConfigurationError(
                "Attribute and template cannot be used together.")

        if not class_:
            raise ConfigurationError(
                "A class must be provided if attribute is used")

    if template:
        template = os.path.abspath(str(_context.path(template)))
        if not os.path.isfile(template):
            raise ConfigurationError("No such file", template)

    # TODO: new __name__ attribute must be tested
    if class_:
        if attribute != '__call__':
            if not hasattr(class_, attribute):
                raise ConfigurationError(
                    "The provided class doesn't have the specified attribute "
                    )
        if template:
            # class and template
            new_class = SimpleViewClass(template, bases=(class_, ), name=name)
        else:
            if not hasattr(class_, 'browserDefault'):
                cdict = {
                    'browserDefault':
                    lambda self, request: (getattr(self, attribute), ())
                    }
            else:
                cdict = {}

            cdict['__name__'] = name
            cdict['__page_attribute__'] = attribute
            cdict.update(getSecurityInfo(class_))
            new_class = type(class_.__name__, (class_, simple,), cdict)

            if attribute != "__call__":
                # in case the attribute does not provide a docstring,
                # ZPublisher refuses to publish it.  So, as a workaround,
                # we provide a stub docstring
                func = getattr(new_class, attribute)
                if not func.__doc__:
                    # cannot test for MethodType/UnboundMethod here
                    # because of ExtensionClass
                    if hasattr(func, 'im_func'):
                        # you can only set a docstring on functions, not
                        # on method objects
                        func = func.im_func
                    func.__doc__ = "Stub docstring to make ZPublisher work"

        if hasattr(class_, '__implements__'):
            classImplements(new_class, IBrowserPublisher)

    else:
        # template
        new_class = SimpleViewClass(template, name=name)

    for n in ('', attribute):
        required[n] = permission

    _handle_allowed_interface(_context, allowed_interface, permission,
                              required)
    _handle_allowed_attributes(_context, allowed_attributes, permission,
                               required)

    _handle_for(_context, for_)

    _configure_z2security(_context, new_class, required)

    _context.action(
        discriminator = ('view', (for_, layer), name, IBrowserRequest),
        callable = handler,
        args = ('registerAdapter',
                new_class, (for_, layer), Interface, name, _context.info),
        )
    def __call__(self):
        (_context, name, (for_, layer), permission, class_,
         allowed_interface, allowed_attributes) = self.args

        name = str(name)  # De-unicode

        required = {}

        cdict = {}
        pages = {}

        for pname, attribute, template in self.pages:

            if template:
                cdict[pname] = ViewPageTemplateFile(template)
                if attribute and attribute != name:
                    cdict[attribute] = cdict[pname]
            else:
                if not hasattr(class_, attribute):
                    raise ConfigurationError("Undefined attribute",
                                             attribute)

            attribute = attribute or pname
            required[pname] = permission

            pages[pname] = attribute

        # This should go away, but noone seems to remember what to do. :-(
        if hasattr(class_, 'publishTraverse'):

            def publishTraverse(self, request, name,
                                pages=pages, getattr=getattr):

                if name in pages:
                    return getattr(self, pages[name])
                view = queryMultiAdapter((self, request), name=name)
                if view is not None:
                    return view

                m = class_.publishTraverse.__get__(self)
                return m(request, name)

        else:
            def publishTraverse(self, request, name,
                                pages=pages, getattr=getattr):

                if name in pages:
                    return getattr(self, pages[name])
                view = queryMultiAdapter((self, request), name=name)
                if view is not None:
                    return view

                raise NotFound(self, name, request)

        cdict['publishTraverse'] = publishTraverse

        if not hasattr(class_, 'browserDefault'):
            if self.default or self.pages:
                default = self.default or self.pages[0][0]
                cdict['browserDefault'] = (
                    lambda self, request, default=default:
                    (self, (default, ))
                    )
            elif providesCallable(class_):
                cdict['browserDefault'] = (
                    lambda self, request: (self, ())
                    )

        if class_ is not None:
            cdict.update(getSecurityInfo(class_))
            bases = (class_, simple)
        else:
            bases = (simple,)

        try:
            cname = str(name)
        except:
            cname = "GeneratedClass"

        cdict['__name__'] = name
        newclass = type(cname, bases, cdict)

        for n in ('',):
            required[n] = permission

        _handle_allowed_interface(_context, allowed_interface, permission,
                                  required)
        _handle_allowed_attributes(_context, allowed_attributes, permission,
                                   required)
        _handle_for(_context, for_)

        _configure_z2security(_context, newclass, required)

        if self.provides is not None:
            _context.action(
                discriminator = None,
                callable = provideInterface,
                args = ('', self.provides)
                )

        _context.action(
            discriminator = ('view', (for_, layer), name, self.provides),
            callable = handler,
            args = ('registerAdapter',
                    newclass, (for_, layer), self.provides, name,
                    _context.info),
            )
Beispiel #12
0
    def __call__(self):
        (_context, name, for_, permission, layer, class_, allowed_interface,
         allowed_attributes) = self.args

        name = str(name)  # De-unicode

        required = {}

        cdict = {}
        pages = {}

        for pname, attribute, template in self.pages:
            if template:
                cdict[pname] = ViewPageTemplateFile(template)
                if attribute and attribute != name:
                    cdict[attribute] = cdict[pname]
            else:
                if not hasattr(class_, attribute):
                    raise ConfigurationError("Undefined attribute", attribute)

            attribute = attribute or pname
            required[pname] = permission

            pages[pname] = attribute

        # This should go away, but noone seems to remember what to do. :-(
        if hasattr(class_, 'publishTraverse'):

            def publishTraverse(self,
                                request,
                                name,
                                pages=pages,
                                getattr=getattr):

                if name in pages:
                    return getattr(self, pages[name])
                view = component.queryMultiAdapter((self, request),
                                                   name=name,
                                                   default=None)
                if view is not None:
                    return view

                m = class_.publishTraverse.__get__(self)
                return m(request, name)

        else:

            def publishTraverse(self,
                                request,
                                name,
                                pages=pages,
                                getattr=getattr):

                if name in pages:
                    return getattr(self, pages[name])
                view = component.queryMultiAdapter((self, request),
                                                   name=name,
                                                   default=None)
                if view is not None:
                    return view

                raise NotFound(self, name, request)

        cdict['publishTraverse'] = publishTraverse

        if not hasattr(class_, 'browserDefault'):
            if self.default or self.pages:
                default = self.default or self.pages[0][0]
                cdict['browserDefault'] = (
                    lambda self, request, default=default: (self, (default, )))
            elif providesCallable(class_):
                cdict['browserDefault'] = (lambda self, request: (self, ()))

        if class_ is not None:
            bases = (class_, ViewMixinForTemplates)
        else:
            bases = (ViewMixinForTemplates, )

        try:
            cname = str(name)
        except:
            cname = "GeneratedClass"

        cdict['__name__'] = name
        newclass = makeClass(cname, bases, cdict)

        _handle_for(_context, for_)

        if self.provides is not None:
            _context.action(discriminator=None,
                            callable=provideInterface,
                            args=('', self.provides))

        _context.action(
            discriminator=('view', for_, name, IBrowserRequest, layer,
                           self.provides),
            callable=handler,
            args=('registerAdapter', newclass, (for_, layer), self.provides,
                  name, _context.info),
        )

        # Security

        _context.action(discriminator=('five:protectClass', newclass),
                        callable=protectClass,
                        args=(newclass, permission))

        if allowed_attributes:
            for attr in allowed_attributes:
                _context.action(discriminator=('five:protectName', newclass,
                                               attr),
                                callable=protectName,
                                args=(newclass, attr, permission))

        # Make everything else private
        allowed = allowed_attributes or []
        private_attrs = [
            name for name in dir(newclass) if (not name.startswith('_')) and (
                name not in allowed) and ismethod(getattr(newclass, name))
        ]
        for attr in private_attrs:
            _context.action(discriminator=('five:protectName', newclass, attr),
                            callable=protectName,
                            args=(newclass, attr, CheckerPrivateId, False))

        # Protect the class
        _context.action(discriminator=('five:initialize:class', newclass),
                        callable=InitializeClass,
                        args=(newclass, ))
Beispiel #13
0
def menuItemDirective(
    _context, name, permission, for_=zope.interface.Interface,
    layer=IDefaultBrowserLayer, view=IBrowserView,
    manager=interfaces.IMenuManager, class_=None, template=None,
    attribute='render', allowed_interface=None, allowed_attributes=None,
    title=None, **kwargs):

    # Security map dictionary
    required = {}

    if title is not None:
        # set i18n aware title
        kwargs['i18nTitle'] = title

    # Get the permission; mainly to correctly handle CheckerPublic.
    permission = _handle_permission(_context, permission)

    # Either the class or template must be specified.
    if not (class_ or template):
        raise ConfigurationError("Must specify a class or template")

    # Make sure that all the non-default attribute specifications are correct.
    if attribute != 'render':
        if template:
            raise ConfigurationError(
                "Attribute and template cannot be used together.")

        # Note: The previous logic forbids this condition to evere occur.
        if not class_:
            raise ConfigurationError(
                "A class must be provided if attribute is used")

    # Make sure that the template exists and that all low-level API methods
    # have the right permission.
    if template:
        template = os.path.abspath(str(_context.path(template)))
        if not os.path.isfile(template):
            raise ConfigurationError("No such file", template)
        required['__getitem__'] = permission

    # Make sure the has the right form, if specified.
    if class_:
        if attribute != 'render':
            if not hasattr(class_, attribute):
                raise ConfigurationError(
                    "The provided class doesn't have the specified attribute "
                    )
        if template:
            # Create a new class for the viewlet template and class.
            new_class = viewlet.SimpleViewletClass(
                template, bases=(class_, ), attributes=kwargs, name=name)
        else:
            if not hasattr(class_, 'browserDefault'):
                cdict = {'browserDefault':
                         lambda self, request: (getattr(self, attribute), ())}
            else:
                cdict = {}

            cdict['__name__'] = name
            cdict['__page_attribute__'] = attribute
            cdict.update(kwargs)
            new_class = type(class_.__name__,
                             (class_, viewlet.SimpleAttributeViewlet), cdict)

        if hasattr(class_, '__implements__'):
            zope.interface.classImplements(new_class, IBrowserPublisher)

    else:
        # Create a new class for the viewlet template alone.
        new_class = viewlet.SimpleViewletClass(template, name=name,
                                               attributes=kwargs)

    # Set up permission mapping for various accessible attributes
    _handle_allowed_interface(
        _context, allowed_interface, permission, required)
    _handle_allowed_attributes(
        _context, allowed_attributes, permission, required)
    _handle_allowed_attributes(
        _context, kwargs.keys(), permission, required)
    _handle_allowed_attributes(
        _context,
        (attribute, 'browserDefault', 'update', 'render', 'publishTraverse'),
        permission, required)

    # Register the interfaces.
    _handle_for(_context, for_)
    zcml.interface(_context, view)

    # Create the security checker for the new class
    zope.security.checker.defineChecker(new_class,
        zope.security.checker.Checker(required))

    # register viewlet
    _context.action(
        discriminator = ('viewlet', for_, layer, view, manager, name),
        callable = zcml.handler,
        args = ('registerAdapter',
                new_class, (for_, layer, view, manager),
                zope.viewlet.interfaces.IViewlet, name, _context.info),)
def page(_context, name, permission, for_,
         layer=IDefaultBrowserLayer, template=None, class_=None,
         allowed_interface=None, allowed_attributes=None,
         attribute='__call__', menu=None, title=None,
         ):

    name = str(name)  # De-unicode
    _handle_menu(_context, menu, title, [for_], name, permission)

    if not (class_ or template):
        raise ConfigurationError("Must specify a class or template")
    if allowed_attributes is None:
        allowed_attributes = []
    if allowed_interface is not None:
        for interface in allowed_interface:
            allowed_attributes.extend(interface.names(all=True))

    if attribute != '__call__':
        if template:
            raise ConfigurationError(
                "Attribute and template cannot be used together.")

        if not class_:
            raise ConfigurationError(
                "A class must be provided if attribute is used")

    if template:
        template = os.path.abspath(str(_context.path(template)))
        if not os.path.isfile(template):
            raise ConfigurationError("No such file", template)

    if class_:
        if attribute != '__call__':
            if not hasattr(class_, attribute):
                raise ConfigurationError(
                    "The provided class doesn't have the specified attribute "
                    )
        cdict = getSecurityInfo(class_)
        cdict['__name__'] = name
        if template:
            new_class = makeClassForTemplate(template, bases=(class_, ),
                                             cdict=cdict, name=name)
        elif attribute != "__call__":
            # we're supposed to make a page for an attribute (read:
            # method) and it's not __call__.  We thus need to create a
            # new class using our mixin for attributes.
            cdict.update({'__page_attribute__': attribute})
            new_class = makeClass(class_.__name__,
                                  (class_, ViewMixinForAttributes),
                                  cdict)

            # in case the attribute does not provide a docstring,
            # ZPublisher refuses to publish it.  So, as a workaround,
            # we provide a stub docstring
            func = getattr(new_class, attribute)
            if not func.__doc__:
                # cannot test for MethodType/UnboundMethod here
                # because of ExtensionClass
                if hasattr(func, 'im_func'):
                    # you can only set a docstring on functions, not
                    # on method objects
                    func = func.im_func
                func.__doc__ = "Stub docstring to make ZPublisher work"
        else:
            # we could use the class verbatim here, but we'll execute
            # some security declarations on it so we really shouldn't
            # modify the original.  So, instead we make a new class
            # with just one base class -- the original
            new_class = makeClass(class_.__name__, 
                                  (class_, BrowserView), cdict)

    else:
        # template
        new_class = makeClassForTemplate(template, name=name)

    _handle_for(_context, for_)

    _context.action(
        discriminator = ('view', for_, name, IBrowserRequest, layer),
        callable = handler,
        args = ('registerAdapter',
                new_class, (for_, layer), Interface, name, _context.info),
        )
    _context.action(
        discriminator = ('five:protectClass', new_class),
        callable = protectClass,
        args = (new_class, permission)
        )
    if allowed_attributes:
        for attr in allowed_attributes:
            _context.action(
                discriminator = ('five:protectName', new_class, attr),
                callable = protectName,
                args = (new_class, attr, permission)
                )
    # Make everything else private
    allowed = [attribute] + (allowed_attributes or [])
    private_attrs = [name for name in dir(new_class)
                     if (not name.startswith('_')) and
                        (name not in allowed) and
                        ismethod(getattr(new_class, name))]
    for attr in private_attrs:
        _context.action(
            discriminator = ('five:protectName', new_class, attr),
            callable = protectName,
            args = (new_class, attr, CheckerPrivateId)
            )
    # Protect the class
    _context.action(
        discriminator = ('five:initialize:class', new_class),
        callable = InitializeClass,
        args = (new_class,)
        )
    def __call__(self):
        (_context, name, for_, permission, layer, class_,
         allowed_interface, allowed_attributes) = self.args

        name = str(name)  # De-unicode

        required = {}

        cdict = {}
        pages = {}

        for pname, attribute, template in self.pages:
            if template:
                cdict[pname] = ViewPageTemplateFile(template)
                if attribute and attribute != name:
                    cdict[attribute] = cdict[pname]
            else:
                if not hasattr(class_, attribute):
                    raise ConfigurationError("Undefined attribute",
                                             attribute)

            attribute = attribute or pname
            required[pname] = permission

            pages[pname] = attribute

        # This should go away, but noone seems to remember what to do. :-(
        if hasattr(class_, 'publishTraverse'):

            def publishTraverse(self, request, name,
                                pages=pages, getattr=getattr):

                if name in pages:
                    return getattr(self, pages[name])
                view = component.queryMultiAdapter((self, request), name=name,
                                                   default=None)
                if view is not None:
                    return view

                m = class_.publishTraverse.__get__(self)
                return m(request, name)

        else:
            def publishTraverse(self, request, name,
                                pages=pages, getattr=getattr):

                if name in pages:
                    return getattr(self, pages[name])
                view = component.queryMultiAdapter((self, request), name=name,
                                                   default=None)
                if view is not None:
                    return view

                raise NotFound(self, name, request)

        cdict['publishTraverse'] = publishTraverse

        if not hasattr(class_, 'browserDefault'):
            if self.default or self.pages:
                default = self.default or self.pages[0][0]
                cdict['browserDefault'] = (
                    lambda self, request, default=default:
                    (self, (default, ))
                    )
            elif providesCallable(class_):
                cdict['browserDefault'] = (
                    lambda self, request: (self, ())
                    )

        if class_ is not None:
            bases = (class_, ViewMixinForTemplates)
        else:
            bases = (ViewMixinForTemplates,)

        try:
            cname = str(name)
        except:
            cname = "GeneratedClass"
            
        cdict['__name__'] = name
        newclass = makeClass(cname, bases, cdict)
        
        _handle_for(_context, for_)

        if self.provides is not None:
            _context.action(
                discriminator = None,
                callable = provideInterface,
                args = ('', self.provides)
                )

        _context.action(
            discriminator = ('view', for_, name, IBrowserRequest, layer,
                             self.provides),
            callable = handler,
            args = ('registerAdapter',
                    newclass, (for_, layer), self.provides, name,
                    _context.info),
            )
        
        # Security
        
        _context.action(
            discriminator = ('five:protectClass', newclass),
            callable = protectClass,
            args = (newclass, permission)
            )
        
        if allowed_attributes:
            for attr in allowed_attributes:
                _context.action(
                    discriminator = ('five:protectName', newclass, attr),
                    callable = protectName,
                    args = (newclass, attr, permission)
                    )
        
        # Make everything else private
        allowed = allowed_attributes or []
        private_attrs = [name for name in dir(newclass)
                         if (not name.startswith('_')) and
                            (name not in allowed) and
                            ismethod(getattr(newclass, name))]
        for attr in private_attrs:
            _context.action(
                discriminator = ('five:protectName', newclass, attr),
                callable = protectName,
                args = (newclass, attr, CheckerPrivateId, False)
                )
        
        # Protect the class
        _context.action(
            discriminator = ('five:initialize:class', newclass),
            callable = InitializeClass,
            args = (newclass,)
            )
def viewletDirective(
    _context, name, permission,
    for_=Interface, layer=IDefaultBrowserLayer, view=IBrowserView,
    manager=interfaces.IViewletManager, class_=None, template=None,
    attribute='render', allowed_interface=None, allowed_attributes=None,
    **kwargs):

    # Either the class or template must be specified.
    if not (class_ or template):
        raise ConfigurationError("Must specify a class or template")

    # Make sure that all the non-default attribute specifications are correct.
    if attribute != 'render':
        if template:
            raise ConfigurationError(
                "Attribute and template cannot be used together.")

        # Note: The previous logic forbids this condition to evere occur.
        if not class_:
            raise ConfigurationError(
                "A class must be provided if attribute is used")

    # Iterate over permissions
    if allowed_attributes is None:
        allowed_attributes = ['render', 'update']
    if allowed_interface is not None:
        for interface in allowed_interface:
            allowed_attributes.extend(interface.names())

    # Make sure that the template exists and that all low-level API methods
    # have the right permission.
    if template:
        template = os.path.abspath(str(_context.path(template)))
        if not os.path.isfile(template):
            raise ConfigurationError("No such file", template)
        allowed_attributes.append('__getitem__')

    # Make sure the has the right form, if specified.
    if class_:
        if attribute != 'render':
            if not hasattr(class_, attribute):
                raise ConfigurationError(
                    "The provided class doesn't have the specified attribute "
                    )
        if template:
            # Create a new class for the viewlet template and class.
            new_class = viewlet.SimpleViewletClass(
                template, bases=(class_, ), attributes=kwargs)
        else:
            if not hasattr(class_, 'browserDefault'):
                cdict = {'browserDefault':
                         lambda self, request: (getattr(self, attribute), ())}
            else:
                cdict = {}

            cdict['__name__'] = name
            cdict['__page_attribute__'] = attribute
            cdict.update(kwargs)
            new_class = type(class_.__name__,
                             (class_, viewlet.SimpleAttributeViewlet), cdict)

    else:
        # Create a new class for the viewlet template alone.
        new_class = viewlet.SimpleViewletClass(template, name=name,
                                               attributes=kwargs)

    # Register the interfaces.
    _handle_for(_context, for_)
    zcml.interface(_context, view)

    # register viewlet
    _context.action(
        discriminator = ('viewlet', for_, layer, view, manager, name),
        callable = zcml.handler,
        args = ('registerAdapter',
                new_class, (for_, layer, view, manager),
                interfaces.IViewlet, name, _context.info),)

    _context.action(
        discriminator = ('five:protectClass', new_class),
        callable = protectClass,
        args = (new_class, permission)
        )
    if allowed_attributes:
        for attr in allowed_attributes:
            _context.action(
                discriminator = ('five:protectName', new_class, attr),
                callable = protectName,
                args = (new_class, attr, permission)
                )
    _context.action(
        discriminator = ('five:initialize:class', new_class),
        callable = InitializeClass,
        args = (new_class,)
        )
Beispiel #17
0
def page(
    _context,
    name,
    permission,
    for_,
    layer=IDefaultBrowserLayer,
    template=None,
    class_=None,
    allowed_interface=None,
    allowed_attributes=None,
    attribute='__call__',
    menu=None,
    title=None,
):

    name = str(name)  # De-unicode
    _handle_menu(_context, menu, title, [for_], name, permission)

    if not (class_ or template):
        raise ConfigurationError("Must specify a class or template")
    if allowed_attributes is None:
        allowed_attributes = []
    if allowed_interface is not None:
        for interface in allowed_interface:
            allowed_attributes.extend(interface.names(all=True))

    if attribute != '__call__':
        if template:
            raise ConfigurationError(
                "Attribute and template cannot be used together.")

        if not class_:
            raise ConfigurationError(
                "A class must be provided if attribute is used")

    if template:
        template = os.path.abspath(str(_context.path(template)))
        if not os.path.isfile(template):
            raise ConfigurationError("No such file", template)

    if class_:
        if attribute != '__call__':
            if not hasattr(class_, attribute):
                raise ConfigurationError(
                    "The provided class doesn't have the specified attribute ")
        cdict = getSecurityInfo(class_)
        cdict['__name__'] = name
        if template:
            new_class = makeClassForTemplate(template,
                                             bases=(class_, ),
                                             cdict=cdict,
                                             name=name)
        elif attribute != "__call__":
            # we're supposed to make a page for an attribute (read:
            # method) and it's not __call__.  We thus need to create a
            # new class using our mixin for attributes.
            cdict.update({'__page_attribute__': attribute})
            new_class = makeClass(class_.__name__,
                                  (class_, ViewMixinForAttributes), cdict)

            # in case the attribute does not provide a docstring,
            # ZPublisher refuses to publish it.  So, as a workaround,
            # we provide a stub docstring
            func = getattr(new_class, attribute)
            if not func.__doc__:
                # cannot test for MethodType/UnboundMethod here
                # because of ExtensionClass
                if hasattr(func, 'im_func'):
                    # you can only set a docstring on functions, not
                    # on method objects
                    func = func.im_func
                func.__doc__ = "Stub docstring to make ZPublisher work"
        else:
            # we could use the class verbatim here, but we'll execute
            # some security declarations on it so we really shouldn't
            # modify the original.  So, instead we make a new class
            # with just one base class -- the original
            new_class = makeClass(class_.__name__, (class_, BrowserView),
                                  cdict)

    else:
        # template
        new_class = makeClassForTemplate(template, name=name)

    _handle_for(_context, for_)

    _context.action(
        discriminator=('view', for_, name, IBrowserRequest, layer),
        callable=handler,
        args=('registerAdapter', new_class, (for_, layer), Interface, name,
              _context.info),
    )
    _context.action(discriminator=('five:protectClass', new_class),
                    callable=protectClass,
                    args=(new_class, permission))
    if allowed_attributes:
        for attr in allowed_attributes:
            _context.action(discriminator=('five:protectName', new_class,
                                           attr),
                            callable=protectName,
                            args=(new_class, attr, permission))
    # Make everything else private
    allowed = [attribute] + (allowed_attributes or [])
    private_attrs = [
        name for name in dir(new_class) if (not name.startswith('_')) and (
            name not in allowed) and ismethod(getattr(new_class, name))
    ]
    for attr in private_attrs:
        _context.action(discriminator=('five:protectName', new_class, attr),
                        callable=protectName,
                        args=(new_class, attr, CheckerPrivateId))
    # Protect the class
    _context.action(discriminator=('five:initialize:class', new_class),
                    callable=InitializeClass,
                    args=(new_class, ))
Beispiel #18
0
def wizardStepDirective(_context,
                        class_,
                        name,
                        permission,
                        for_=zope.interface.Interface,
                        layer=IDefaultBrowserLayer,
                        wizard=interfaces.IWizard,
                        provides=interfaces.IStep,
                        allowed_interface=None,
                        allowed_attributes=None,
                        **kwargs):

    # Security map dictionary
    required = {}

    # Get the permission; mainly to correctly handle CheckerPublic.
    permission = _handle_permission(_context, permission)

    # The class must be specified.
    if not class_:
        raise ConfigurationError("Must specify a class.")

    if not zope.interface.interfaces.IInterface.providedBy(provides):
        raise ConfigurationError("Provides interface provide IInterface.")

    ifaces = list(zope.interface.Declaration(provides).flattened())
    if interfaces.IPagelet not in ifaces:
        raise ConfigurationError("Provides interface must inherit IPagelet.")

    if not interfaces.IWizard.implementedBy(wizard):
        raise ConfigurationError("Provides interface must inherit IWizard.")

    # Build a new class that we can use different permission settings if we
    # use the class more then once.
    cdict = {}
    cdict['__name__'] = name
    cdict.update(kwargs)
    new_class = type(class_.__name__, (class_, step.Step), cdict)

    # Set up permission mapping for various accessible attributes
    _handle_allowed_interface(_context, allowed_interface, permission,
                              required)
    _handle_allowed_attributes(_context, allowed_attributes, permission,
                               required)
    _handle_allowed_attributes(_context, kwargs.keys(), permission, required)
    _handle_allowed_attributes(
        _context,
        ('__call__', 'browserDefault', 'update', 'render', 'publishTraverse'),
        permission, required)

    # Register the interfaces.
    _handle_for(_context, for_)

    # provide the custom provides interface if not allready provided
    if not provides.implementedBy(new_class):
        zope.interface.classImplements(new_class, provides)

    # Create the security checker for the new class
    zope.security.checker.defineChecker(
        new_class, zope.security.checker.Checker(required))

    # register pagelet
    _context.action(discriminator=('pagelet', for_, layer, name),
                    callable=zope.component.zcml.handler,
                    args=('registerAdapter', new_class, (for_, layer, wizard),
                          provides, name, _context.info))