tags:

views:

140

answers:

1

I have a section of my zope 2 site which uses an interim macro between the 'content' and the site-wide macro. I don't want to apply security to the folder, but I would like the interim macro to redirect users to a login screen if they try to load a page that uses it.

An example of this would be this:

page_html contains the content, it uses the macro in special_template, which then slots into a macro in standard_template. Therefore I want it to redirect to the login screen. If page_html didn't use special_template, but went straight to standard_template (which is what most of the pages on the site do), I would not want it to redirect.

How could I achieve this?

A: 

First of all, why not restructure your site to put all these pages that require authentication in locations you can protect with Zope permissions? A custom (local) workflow can apply permissions on a state-by-state and location-by-location basis, thus using Zope's own automatic authentication framework. If you don't use a workflow, a custom type can still apply permissions that are acquired by anything below it in URL space.

You can create a method (a Zope3 view, a Python Script in a skin layer, a method on a content class in your acquisition context, an External Method, in rough order of best practices) that is called from your special_template macro by means of a tal:define statement. I'll assign the output to a dummy variable here because you don't care about that, we'll use it for it's side effects. The following example assumes you've gone the Z3 view way:

<body tal:define="dummy context/@@redirect_if_anonymous">

This will instanciate the view registered with the name redirect_if_anonymous. In the view you can then test if your web visitor has been authenticated, using standard Zope API methods or a test for a cookie, depending on your application. Here is a standard API example, it'll raise Unauthorized to force a login.

from Products.Five import BrowserView
from AccessControl import getSecurityManager, Unauthorized
from AccessControl.SpecialUsers import nobody

class RedirectAnonymous(BrowserView):
    def __call__(self):
        sm = getSecurityManager()
        user = sm.getUser()
        if user is None or user is nobody:
             raise Unauthorized

If all you want is a redirect to another location, simply use response.redirect():

url = self.request['URL0'] + '/login.html'
self.request.response.redirect(url)

If you want to test for cookies first, cookies are part of the request variables:

if 'mycookie' not in self.request.cookies:
    self.request.response.redirect(url)
Martijn Pieters