Персональные инструменты
Вы здесь: Главная Блоги 2010 Август

Август

Sub-archives

2010-08-22

Маскировка под другого пользователя в Zope 3 представлении браузера

by Ирина Бессарабова — last modified 2010-08-22 19:15

Как и у Josh Johnson, автора статьи, чей вольный перевод я привожу здесь, у меня тоже была необходимость выполнять кое-какие действия от пользователя с ролью Anonymous, так, чтобы при этом не возникала ошибка авторизации пользователя.

Возьмем, например, задачу добавления анонимными пользователеми контента в папку. Они заполняют форму, которая проходит валидацию и создается новый объект. Звучит просто. Однако, на практике это не так :)

В Zope 2 есть Proxy Roles для скриптов, однако  если ваша форма создана в zope3 стиле в виде представления браузера, для вас это не вариант. 

В решении этой задачи может помочь модуль AccessControl, который входит в состав Zope 3.

Код может выглядеть как-то так:

from AccessControl.SecurityManagement import newSecurityManager, getSecurityManager, setSecurityManager
from Products.CMFCore.utils import getToolByName
...
class MyViewClass(SomeBaseViewClass):
    # without going into detail here, assume that __init__ is passed a context and request object
    # that are set as instance properties.

    def someProcessorMethod(self):
        # I've created a folder called "Special Folder" at the root of my Plone site. 

        portal = getToolByName(self.context, 'portal_url').getPortalObject() 

        owner = portal['special-folder'].getWrappedOwner()

        # stash the existing security manager so we can restore it
        old_security_manager = getSecurityManager()

        # create a new context, as the owner of the folder
        newSecurityManager(self.request, user)

        try:
            # make the content
            portal['special-folder'].invokeFactory('Document',
                                                   'anonymous-content-ftw',
                                                   title='Anonymous Content FTW!')
        except:
            # we want to ensure that setSecurityManager gets called
            # in reality you should do more here!
            pass

        # restore the original context
        setSecurityManager(old_security_manager)

 

Вот и все, что нужно сделать. Одно из преимуществ такого подхода это то, что владелец папки может измениться, а код все равно будет работать.

При использовании этого кода нужно быть особенно осторожным с тем, где его позволено вызывать. Например, если представление может применяться везде (в атрибуте for в директиве регистрации представления стоит *), то можно представить какой беспорядок может натворить анонимный пользователь на вашем сайте.

Кроме того, весь код, выполняющийся от имени владельца папки, необходимо заключить в блок try catch, для того, чтобы быть уверенным, что если даже в процессе его выполнения произойдет ошибка, менеджер безопасности восстановится в свое прежнее состояние.