コード例 #1
0
class NyTalkBackConsultation(Implicit, NyContentData, NyContentType,
                             NyAttributes, NyProperties, NyRoleManager,
                             NyContainer, NyNonCheckControl, utils,
                             NyFolderBase):
    """ """

    meta_type = METATYPE_TALKBACKCONSULTATION
    meta_label = LABEL_OBJECT

    meta_types = [
        {
            'name': METATYPE_TALKBACKCONSULTATION_SECTION,
            'action': 'addSection',
            'permission': PERMISSION_MANAGE_TALKBACKCONSULTATION
        },
    ]

    icon = 'misc_/NaayaContent/NyTalkBackConsultation.gif'
    icon_marked = 'misc_/NaayaContent/NyTalkBackConsultation_marked.gif'

    security = ClassSecurityInfo()

    edit_access = NyAccess(
        'edit_access', {
            PERMISSION_REVIEW_TALKBACKCONSULTATION: "Submit comments",
            PERMISSION_MANAGE_TALKBACKCONSULTATION: "Administer consultation",
            PERMISSION_INVITE_TO_TALKBACKCONSULTATION: "Send invitations",
        })

    section_sort_order = tuple()

    def __init__(self, id, contributor):
        """ """
        self.id = id
        self.contributor = contributor
        NyContainer.__dict__['__init__'](self)
        NyProperties.__dict__['__init__'](self)
        self.invitations = InvitationsContainer('invitations')
        self.submitted = 1

    def set_allow_reviewer_invites(self, allow):
        perm = '_Naaya___Invite_to_TalkBack_Consultation_Permission'
        roles = getattr(self, perm, [])

        if allow and 'Reviewer' not in roles:
            new_roles = roles + ['Reviewer']
        elif not allow and 'Reviewer' in roles:
            new_roles = tuple(role for role in roles if role != 'Reviewer')
        else:
            new_roles = roles

        if new_roles:
            setattr(self, perm, new_roles)
        else:
            if hasattr(self, perm):
                delattr(self, perm)

    def get_allow_reviewer_invites(self):
        perm = '_Naaya___Invite_to_TalkBack_Consultation_Permission'
        roles = getattr(self, perm, [])
        return ('Reviewer' in roles)

    allow_reviewer_invites = property(get_allow_reviewer_invites,
                                      set_allow_reviewer_invites)

    security.declareProtected(PERMISSION_MANAGE_TALKBACKCONSULTATION,
                              'saveProperties')

    def saveProperties(self, REQUEST=None, **kwargs):
        """ """
        if not self.checkPermissionEditObject():
            raise EXCEPTION_NOTAUTHORIZED(EXCEPTION_NOTAUTHORIZED_MSG)

        if REQUEST is not None:
            schema_raw_data = dict(REQUEST.form)
        else:
            schema_raw_data = kwargs
        _lang = schema_raw_data.pop('_lang', schema_raw_data.pop('lang', None))
        _releasedate = self.process_releasedate(
            schema_raw_data.pop('releasedate', ''), self.releasedate)

        form_errors = self.process_submitted_form(
            schema_raw_data, _lang, _override_releasedate=_releasedate)

        if not form_errors:
            self._p_changed = True
            self.recatalogNyObject(self)
            # log date
            contributor = self.REQUEST.AUTHENTICATED_USER.getUserName()
            auth_tool = self.getAuthenticationTool()
            auth_tool.changeLastPost(contributor)
            notify(NyContentObjectEditEvent(self, contributor))
            if REQUEST:
                self.setSessionInfoTrans(MESSAGE_SAVEDCHANGES,
                                         date=self.utGetTodayDate())
                REQUEST.RESPONSE.redirect('%s/edit_html?lang=%s' %
                                          (self.absolute_url(), _lang))
        else:
            if REQUEST is not None:
                self._prepare_error_response(REQUEST, form_errors,
                                             schema_raw_data)
                REQUEST.RESPONSE.redirect('%s/edit_html?lang=%s' %
                                          (self.absolute_url(), _lang))
            else:
                raise ValueError(form_errors.popitem()[1])  # pick an error

    security.declareProtected(view, 'get_consultation')

    def get_consultation(self):
        return self

    security.declareProtected(view, 'list_sections')

    def list_sections(self):
        """ """
        metatypes = [METATYPE_TALKBACKCONSULTATION_SECTION]
        sections = dict(self.objectItems(metatypes))

        output = []
        for section_id in self.section_sort_order:
            if section_id in sections:
                output.append(sections.pop(section_id))

        output.extend(
            sorted(sections.values(), key=operator.attrgetter('title')))

        return output

    security.declareProtected(PERMISSION_MANAGE_TALKBACKCONSULTATION,
                              'save_sort_order')

    def save_sort_order(self, sort_section_id, REQUEST=None):
        """ save the sort order of sections """
        self.section_sort_order = tuple(sort_section_id)
        if REQUEST is not None:
            REQUEST.RESPONSE.redirect(self.absolute_url())

    _comments_atom = NaayaPageTemplateFile('zpt/comments_atom', globals(),
                                           'tbconsultation_comments_atom')
    security.declareProtected(view, 'comments_atom')

    def comments_atom(self, REQUEST=None, days=2):
        """ ATOM feed with consultation comments """

        if isinstance(days, basestring):
            try:
                days = int(days)
            except:
                days = 2

        cutoff = DateTime() - days
        comments_list = []
        for section in self.list_sections():
            for paragraph in section.get_paragraphs():
                for comment in paragraph.get_comments():
                    if comment.comment_date < cutoff:
                        continue
                    comments_list.append(comment)
        comments_list.sort(key=operator.attrgetter('comment_date'),
                           reverse=True)

        if comments_list:
            feed_updated = comments_list[0].comment_date
        else:
            feed_updated = DateTime()

        def atom_date_format(date):
            d = DT2dt(date).strftime('%Y-%m-%dT%H:%M:%S%z')
            return d[:-2] + ':' + d[-2:]

        if REQUEST is not None:
            REQUEST.RESPONSE.setHeader('Content-Type', 'application/atom+xml')

        return self._comments_atom(comments_list=comments_list,
                                   atom_date_format=atom_date_format,
                                   feed_updated=feed_updated)

    security.declareProtected(view, 'get_start_date')

    def get_start_date(self):
        """ Returns the start date in dd/mm/yyyy string format. """

        return self.utConvertDateTimeObjToString(self.start_date)

    security.declareProtected(view, 'get_end_date')

    def get_end_date(self):
        """ Returns the end date in dd/mm/yyyy string format. """

        return self.utConvertDateTimeObjToString(self.end_date)

    security.declareProtected(view, 'get_days_left')

    def get_days_left(self):
        """ Returns the remaining days for the consultation
        or the number of days before it starts """
        today = self.utGetTodayDate().earliestTime()
        if not self.start_date or not self.end_date:
            return (1, 0)

        after_end_date = self.end_date + 1
        if self.start_date.lessThanEqualTo(today):
            return (1, int(str(after_end_date - today).split('.')[0]))
        else:
            return (0, int(str(self.start_date - today).split('.')[0]))

    security.declareProtected(view_management_screens, 'manage_options')

    def manage_options(self):
        """ """

        l_options = (NyContainer.manage_options[0], )
        l_options += ({'label': 'View', 'action': 'index_html'},) + \
            NyContainer.manage_options[3:8]
        return l_options

    security.declareProtected(PERMISSION_MANAGE_TALKBACKCONSULTATION,
                              'delete_sections')

    def delete_sections(self, del_section_id, REQUEST=None):
        """ remove the specified sections """
        self.manage_delObjects(list(del_section_id))
        self.setSessionInfoTrans('Removed ${count} sections.',
                                 count=str(len(del_section_id)))
        if REQUEST is not None:
            REQUEST.RESPONSE.redirect(self.absolute_url())

    def get_user_name(self):
        # first, check if we have an invite key
        invitation = self.invitations.get_current_invitation(self.REQUEST)
        if invitation is not None:
            return invitation.name

        # no invite key; look for current Zope user
        auth_tool = self.getAuthenticationTool()
        userid = auth_tool.get_current_userid()

        if userid is None:  # anonymous user
            return None

        name = auth_tool.name_from_userid(userid)
        if name == '':
            name = userid
        return name

    def get_user_name_or_userid(self, userid=None):
        if userid is None:
            return self.get_user_name()

        auth_tool = self.getAuthenticationTool()
        name = auth_tool.name_from_userid(userid)
        if name == '':
            name = userid

        return name

    def checkTalkBackConsultationUser(self):
        """
        Checks if the user is logged in and has reviewer rights:
        0 if user is anonymous,
        1 if user has reviewer role
        2 if user doesn't have reviewer role
        """
        review_check = self.checkPermissionReviewTalkBackConsultation()

        if self.isAnonymousUser():
            return 0
        elif review_check:
            return 1
        elif not review_check:
            return 2

    security.declareProtected(view, 'check_cannot_comment')

    def check_cannot_comment(self):
        """ """

        if not self.checkPermissionReviewTalkBackConsultation():
            if self.isAnonymousUser():
                return 'not-logged-in'
            else:
                return 'no-permission'

        if self.get_days_left()[1] <= 0 and not (
                self.checkPermissionManageTalkBackConsultation() or
                self.checkPermissionReviewTalkBackConsultationAfterDeadline()):
            return 'deadline-reached'

    security.declareProtected(PERMISSION_COMMENTS_ADD, 'log_in_authenticated')

    def log_in_authenticated(self, REQUEST=None):
        """ Log in user and redirect to TalkBack Consultation index """
        if REQUEST is not None:
            self.REQUEST.RESPONSE.redirect(self.absolute_url())

    # permissions
    def checkPermissionReviewTalkBackConsultation(self):
        """
        Check for reviewing the TalkBack Consultation.
        """
        return self.checkPermission(PERMISSION_REVIEW_TALKBACKCONSULTATION)

    security.declareProtected(
        PERMISSION_REVIEW_TALKBACKCONSULTATION_AFTER_DEADLINE,
        'review_after_deadline')

    def review_after_deadline(self):
        """
        Dummy function to register the permission.
        """
        raise NotImplementedError

    def checkPermissionReviewTalkBackConsultationAfterDeadline(self):
        """
        Check for reviewing the TalkBack Consultation
        after the deadline has passed.
        """
        return self.checkPermission(
            PERMISSION_REVIEW_TALKBACKCONSULTATION_AFTER_DEADLINE)

    def checkPermissionManageTalkBackConsultation(self):
        """
        Check for managing the TalkBack Consultation.
        """
        return self.checkPermission(PERMISSION_MANAGE_TALKBACKCONSULTATION)

    def checkPermissionInviteToTalkBackConsultation(self):
        """
        Check for inviting others to the TalkBack Consultation.
        """
        return self.checkPermission(PERMISSION_INVITE_TO_TALKBACKCONSULTATION)

    def own_comments(self):
        """
        Check if the current user has any comments on the consultation
        """
        return [
            comment for comment in self.admin_comments._all_comments()
            if comment['comment'].contributor ==
            self.REQUEST.AUTHENTICATED_USER.getUserName()
        ]

    security.declareProtected(view, 'custom_editor')

    def custom_editor(self, editor_tool, lang, dom_id):
        extra_options = {
            'content_css':
            self.absolute_url() + '/misc_/NaayaContent/tb-editor.css',
            'theme_advanced_buttons1':
            'bold,italic,underline,strikethrough,sub,sup,forecolor,'
            'backcolor,removeformat,separator,'
            'bullist,numlist,separator,'
            'justifyleft,justifycenter,justifyright,justifyfull,separator,'
            'link,unlink,hr,image,separator,'
            'pastetext,pasteword,cleanup,code,help',
            'theme_advanced_buttons2':
            '',
        }
        return editor_tool.render(dom_id,
                                  lang,
                                  image_support=True,
                                  extra_options=extra_options)

    security.declareProtected(view, 'get_files')

    def get_files(self):
        """ Get a list of all files attached to the consultation"""
        return [ob for ob in self.objectValues('Naaya Blob File')]

    security.declareProtected(view, 'findUsers')

    def findUsers(self, search_param, search_term):
        """ """
        if len(search_term) == 0:
            return []
        return json.dumps(findUsers(self.getSite(), search_param, search_term))

    addSection = addSection

    # zmi pages
    security.declareProtected(view_management_screens, 'manage_edit_html')
    manage_edit_html = PageTemplateFile('zpt/talkbackconsultation_manage_edit',
                                        globals())

    # site pages
    security.declareProtected(view, 'index_html')
    index_html = NaayaPageTemplateFile('zpt/talkbackconsultation_index',
                                       globals(), 'tbconsultation_index')

    # standard_template_macro, header and footer templates are proxied
    # since invited reviewers have "View" permission only in this folder;
    # if the consultation is restricted, they would not be able to see
    # consultation pages.
    def standard_html_header(self, *args, **kwargs):
        return self.aq_parent.standard_html_header(*args, **kwargs)

    def standard_html_footer(self, *args, **kwargs):
        return self.aq_parent.standard_html_footer(*args, **kwargs)

    def standard_template_macro(self, *args, **kwargs):
        return self.aq_parent.standard_template_macro(*args, **kwargs)

    security.declareProtected(PERMISSION_MANAGE_TALKBACKCONSULTATION,
                              'edit_html')
    edit_html = NaayaPageTemplateFile('zpt/talkbackconsultation_edit',
                                      globals(), 'tbconsultation_edit')

    security.declareProtected(PERMISSION_MANAGE_TALKBACKCONSULTATION,
                              'section_add_html')
    section_add_html = addSection_html

    __allow_groups__ = InvitationUsersTool()
    _View_Permission = ['InvitedReviewer']
    _Naaya___Review_TalkBack_Consultation_Permission = ['InvitedReviewer']
    __ac_roles__ = ['InvitedReviewer']

    admin_comments = CommentsAdmin('admin_comments')
コード例 #2
0
class NyTalkBackConsultation(NyAttributes, Implicit, NyProperties, NyContainer,
                             NyNonCheckControl, utils):
    """ """

    meta_type = METATYPE_TALKBACKCONSULTATION
    meta_label = LABEL_OBJECT

    meta_types = [
        {
            'name': METATYPE_TALKBACKCONSULTATION_SECTION,
            'action': 'addSection',
            'permission': PERMISSION_MANAGE_TALKBACKCONSULTATION
        },
    ]

    icon = 'misc_/NaayaContent/NyTalkBackConsultation.gif'
    icon_marked = 'misc_/NaayaContent/NyTalkBackConsultation_marked.gif'

    title = LocalProperty('title')
    description = LocalProperty('description')

    security = ClassSecurityInfo()

    def __init__(self, id, title, description, sortorder, start_date, end_date,
                 public_registration, allow_file, allow_reviewer_invites,
                 contributor, releasedate, lang):
        """ """

        self.id = id
        self.contributor = contributor
        NyContainer.__dict__['__init__'](self)
        self.save_properties(title, description, sortorder, start_date,
                             end_date, public_registration, allow_file,
                             allow_reviewer_invites, releasedate, lang)

        NyProperties.__dict__['__init__'](self)
        self.invitations = InvitationsContainer('invitations')
        self.submitted = 1

    def set_allow_reviewer_invites(self, allow):
        perm = '_Naaya___Invite_to_TalkBack_Consultation_Permission'
        roles = getattr(self, perm, [])

        if allow and 'Reviewer' not in roles:
            roles.append('Reviewer')
        elif not allow and 'Reviewer' in roles:
            roles.remove('Reviewer')

        if roles:
            setattr(self, perm, roles)
        else:
            if hasattr(self, perm):
                delattr(self, perm)

    def get_allow_reviewer_invites(self):
        perm = '_Naaya___Invite_to_TalkBack_Consultation_Permission'
        roles = getattr(self, perm, [])
        return ('Reviewer' in roles)

    allow_reviewer_invites = property(get_allow_reviewer_invites,
                                      set_allow_reviewer_invites)

    security.declarePrivate('save_properties')

    def save_properties(self, title, description, sortorder, start_date,
                        end_date, public_registration, allow_file,
                        allow_reviewer_invites, releasedate, lang):

        self._setLocalPropValue('title', lang, title)
        self._setLocalPropValue('description', lang, description)

        if not hasattr(self, 'imageContainer'):
            self.imageContainer = NyImageContainer(self, True)

        if start_date:
            self.start_date = self.utConvertStringToDateTimeObj(start_date)
        else:
            self.start_date = self.utGetTodayDate()

        if end_date:
            self.end_date = self.utConvertStringToDateTimeObj(end_date)
        else:
            self.end_date = self.utGetTodayDate()

        try:
            self.sortorder = abs(int(sortorder))
        except:
            self.sortorder = DEFAULT_SORTORDER

        self.releasedate = releasedate
        self.public_registration = public_registration
        self.allow_file = allow_file
        self.allow_reviewer_invites = allow_reviewer_invites

    security.declareProtected(PERMISSION_MANAGE_TALKBACKCONSULTATION,
                              'saveProperties')

    def saveProperties(self,
                       title='',
                       description='',
                       sortorder='',
                       start_date='',
                       end_date='',
                       public_registration='',
                       allow_file='',
                       allow_reviewer_invites=False,
                       lang='',
                       REQUEST=None):
        """ """

        if not title:
            self.setSession('title', title)
            self.setSession('description', description)
            self.setSessionErrors(['The Title field must have a value.'])
            if REQUEST:
                return REQUEST.RESPONSE.redirect('%s/edit_html?lang=%s' %
                                                 (self.absolute_url(), lang))
            else:
                raise ValueError('The title field must have a value.')

        releasedate = self.releasedate
        self.updateRequestRoleStatus(public_registration, lang)
        self.save_properties(title, description, sortorder, start_date,
                             end_date, public_registration, allow_file,
                             allow_reviewer_invites, releasedate, lang)

        if REQUEST:
            self.setSessionInfo([MESSAGE_SAVEDCHANGES % self.utGetTodayDate()])
            REQUEST.RESPONSE.redirect('%s/edit_html?lang=%s' %
                                      (self.absolute_url(), lang))

    security.declarePrivate('addDynProp')

    def addDynProp(self):
        """ """
        dynprop_tool = self.getDynamicPropertiesTool()
        if not hasattr(dynprop_tool, METATYPE_OBJECT):
            dynprop_tool.manage_addDynamicPropertiesItem(id=METATYPE_OBJECT,
                                                         title=METATYPE_OBJECT)
            dynprop_tool._getOb(METATYPE_OBJECT).manageAddDynamicProperty(
                id='show_contributor_request_role',
                name=
                'Allow visitors to register as reviewers for this consultation',
                type='boolean')

    security.declareProtected(PERMISSION_MANAGE_TALKBACKCONSULTATION,
                              'updateRequestRoleStatus')

    def updateRequestRoleStatus(self, public_registration, lang):
        """ Allow public registration for this consultation """
        if public_registration:
            self.updateDynamicProperties(
                self.processDynamicProperties(
                    METATYPE_TALKBACKCONSULTATION,
                    {'show_contributor_request_role': 'on'}), lang)
        if not public_registration:
            self.updateDynamicProperties(
                self.processDynamicProperties(
                    METATYPE_TALKBACKCONSULTATION,
                    {'show_contributor_request_role': ''}), lang)

    security.declareProtected(PERMISSION_MANAGE_TALKBACKCONSULTATION,
                              'checkReviewerRole')

    def checkReviewerRole(self):
        """
        Checks if the 'Reviewer' role exists,
        creates and adds review permissions if it doesn't exist
        """

        auth_tool = self.getAuthenticationTool()
        roles = auth_tool.list_all_roles()
        PERMISSION_GROUP = 'Review content'

        if PERMISSION_GROUP not in auth_tool.listPermissions().keys():
            auth_tool.addPermission(
                PERMISSION_GROUP,
                'Allow posting reviews/comments to consultation objects.',
                [PERMISSION_REVIEW_TALKBACKCONSULTATION])
        else:
            permissions = auth_tool.getPermission(PERMISSION_GROUP).get(
                'permissions', [])
            if PERMISSION_REVIEW_TALKBACKCONSULTATION not in permissions:
                permissions.append(PERMISSION_REVIEW_TALKBACKCONSULTATION)
                auth_tool.editPermission(
                    PERMISSION_GROUP,
                    'Allow posting reviews/comments to consultation objects.',
                    permissions)

        if 'Reviewer' not in roles:
            auth_tool.addRole('Reviewer', [PERMISSION_GROUP])
        else:
            role_permissions = auth_tool.getRolePermissions('Reviewer')
            if PERMISSION_GROUP not in role_permissions:
                role_permissions.append(PERMISSION_GROUP)
                auth_tool.editRole('Reviewer', role_permissions)

        #give permissions to administrators and reviewers
        admin_permissions = self.permissionsOfRole('Administrator')
        site = self.getSite()
        if PERMISSION_MANAGE_TALKBACKCONSULTATION not in admin_permissions:
            site.manage_permission(PERMISSION_MANAGE_TALKBACKCONSULTATION,
                                   ('Administrator', ),
                                   acquire=1)
            site.manage_permission(PERMISSION_REVIEW_TALKBACKCONSULTATION, (
                'Administrator',
                'Reviewer',
            ),
                                   acquire=1)

    security.declareProtected(view, 'get_consultation')

    def get_consultation(self):
        return self

    security.declareProtected(view, 'list_sections')

    def list_sections(self):
        """ """
        sections = self.objectValues([METATYPE_TALKBACKCONSULTATION_SECTION])
        sections.sort(lambda x, y: cmp(x.title, y.title))
        return sections

    security.declareProtected(view, 'get_start_date')

    def get_start_date(self):
        """ Returns the start date in dd/mm/yyyy string format. """

        return self.utConvertDateTimeObjToString(self.start_date)

    security.declareProtected(view, 'get_end_date')

    def get_end_date(self):
        """ Returns the end date in dd/mm/yyyy string format. """

        return self.utConvertDateTimeObjToString(self.end_date)

    security.declareProtected(view, 'get_days_left')

    def get_days_left(self):
        """ Returns the remaining days for the consultation or the number of days before it starts """

        today = self.utGetTodayDate().earliestTime()
        if not self.start_date or not self.end_date:
            return (1, 0)

        if self.start_date.lessThanEqualTo(today):
            return (1, int(str(self.end_date - today).split('.')[0]))
        else:
            return (0, int(str(self.start_date - today).split('.')[0]))

    security.declareProtected(view_management_screens, 'manage_options')

    def manage_options(self):
        """ """

        l_options = (NyContainer.manage_options[0], )
        l_options += ({'label': 'View', 'action': 'index_html'},) + \
                  NyContainer.manage_options[3:8]
        return l_options

    def get_user_name(self):
        # first, check if we have an invite key
        invitation = self.invitations.get_current_invitation(self.REQUEST)
        if invitation is not None:
            return invitation.name

        # no invite key; look for current Zope user
        auth_tool = self.getAuthenticationTool()
        userid = auth_tool.get_current_userid()

        if userid is None:  # anonymous user
            return None

        name = auth_tool.name_from_userid(userid)
        if name == '':
            name = userid
        return name

    def get_user_name_or_userid(self, userid=None):
        if userid is None:
            return self.get_user_name()

        auth_tool = self.getAuthenticationTool()
        name = auth_tool.name_from_userid(userid)
        if name == '':
            name = userid

        return name

    def checkTalkBackConsultationUser(self):
        """
        Checks if the user is logged in and has reviewer rights:
        0 if user is anonymous,
        1 if user has reviewer role
        2 if user doesn't have reviewer role
        """
        review_check = self.checkPermissionReviewTalkBackConsultation()

        if self.isAnonymousUser(): return 0
        elif review_check: return 1
        elif not review_check: return 2

    security.declareProtected(view, 'check_cannot_comment')

    def check_cannot_comment(self):
        """ """

        if not self.checkPermissionReviewTalkBackConsultation():
            return 'no-permission'

        if self.get_days_left()[1] <= 0:
            return 'deadline-reached'

    security.declareProtected(PERMISSION_COMMENTS_ADD, 'log_in_authenticated')

    def log_in_authenticated(self, REQUEST=None):
        """ Log in user and redirect to TalkBack Consultation index """
        if REQUEST is not None:
            self.REQUEST.RESPONSE.redirect(self.absolute_url())

    #permissions
    def checkPermissionReviewTalkBackConsultation(self):
        """
        Check for reviewing the TalkBack Consultation.
        """
        return self.checkPermission(PERMISSION_REVIEW_TALKBACKCONSULTATION)

    def checkPermissionManageTalkBackConsultation(self):
        """
        Check for managing the TalkBack Consultation.
        """
        return self.checkPermission(PERMISSION_MANAGE_TALKBACKCONSULTATION)

    def checkPermissionInviteToTalkBackConsultation(self):
        """
        Check for inviting others to the TalkBack Consultation.
        """
        return self.checkPermission(PERMISSION_INVITE_TO_TALKBACKCONSULTATION)

    security.declareProtected(view, 'custom_editor')

    def custom_editor(self, editor_tool, lang, dom_id):
        extra_options = {
            'content_css':
            [self.absolute_url() + '/misc_/NaayaContent/tb-editor.css'],
            'theme_advanced_buttons1': [
                'bold,italic,underline,strikethrough,sub,sup,forecolor,'
                'backcolor,removeformat,separator,'
                'bullist,numlist,separator,'
                'justifyleft,justifycenter,justifyright,justifyfull,separator,'
                'link,unlink,hr,image,separator,'
                'pastetext,pasteword,cleanup,code,help'
            ],
            'theme_advanced_buttons2': [''],
        }
        return editor_tool.render(dom_id,
                                  lang,
                                  image_support=True,
                                  extra_options=extra_options)

    addSection = addSection

    #zmi pages
    security.declareProtected(view_management_screens, 'manage_edit_html')
    manage_edit_html = PageTemplateFile('zpt/talkbackconsultation_manage_edit',
                                        globals())

    #site pages
    security.declareProtected(view, 'index_html')
    index_html = NaayaPageTemplateFile('zpt/talkbackconsultation_index',
                                       globals(), 'tbconsultation_index')

    # header and footer templates are proxied since invited reviewers
    # have "View" permission only in this folder; if the consultation
    # is restricted, they would not be able to see consultation pages.
    def standard_html_header(self, *args, **kwargs):
        return self.aq_parent.standard_html_header(*args, **kwargs)

    def standard_html_footer(self, *args, **kwargs):
        return self.aq_parent.standard_html_footer(*args, **kwargs)

    security.declareProtected(PERMISSION_MANAGE_TALKBACKCONSULTATION,
                              'edit_html')
    edit_html = PageTemplateFile('zpt/talkbackconsultation_edit', globals())

    security.declareProtected(PERMISSION_MANAGE_TALKBACKCONSULTATION,
                              'section_add_html')
    section_add_html = addSection_html

    __allow_groups__ = InvitationUsersTool()
    _View_Permission = ['InvitedReviewer']
    _Naaya___Review_TalkBack_Consultation_Permission = ['InvitedReviewer']
    __ac_roles__ = ['InvitedReviewer']

    admin_comments = CommentsAdmin('admin_comments')
コード例 #3
0
class NyTalkBackConsultation(Implicit, NyContentData, NyContentType,
                             NyAttributes, NyProperties, NyRoleManager,
                             NyContainer, NyNonCheckControl, utils,
                             NyFolderBase):
    """ """

    meta_type = METATYPE_TALKBACKCONSULTATION
    meta_label = LABEL_OBJECT

    meta_types = [
        {'name': METATYPE_TALKBACKCONSULTATION_SECTION, 'action': 'addSection',
            'permission': PERMISSION_MANAGE_TALKBACKCONSULTATION},
    ]

    icon = 'misc_/NaayaContent/NyTalkBackConsultation.gif'
    icon_marked = 'misc_/NaayaContent/NyTalkBackConsultation_marked.gif'

    security = ClassSecurityInfo()

    edit_access = NyAccess('edit_access', {
        PERMISSION_REVIEW_TALKBACKCONSULTATION: "Submit comments",
        PERMISSION_REVIEW_TALKBACKCONSULTATION_AFTER_DEADLINE:
            "Submit comments after deadline",
        PERMISSION_MANAGE_TALKBACKCONSULTATION: "Administer consultation",
        PERMISSION_INVITE_TO_TALKBACKCONSULTATION: "Send invitations",
    })

    section_sort_order = tuple()

    def __init__(self, id, contributor):
        """ """
        self.id = id
        self.contributor = contributor
        NyContainer.__dict__['__init__'](self)
        NyProperties.__dict__['__init__'](self)
        self.invitations = InvitationsContainer('invitations')
        self.submitted = 1

    def set_allow_reviewer_invites(self, allow):
        perm = '_Naaya___Invite_to_TalkBack_Consultation_Permission'
        roles = getattr(self, perm, [])

        if allow and 'Reviewer' not in roles:
            new_roles = roles + ['Reviewer']
        elif not allow and 'Reviewer' in roles:
            new_roles = tuple(role for role in roles if role != 'Reviewer')
        else:
            new_roles = roles

        if new_roles:
            setattr(self, perm, new_roles)
        else:
            if hasattr(self, perm):
                delattr(self, perm)

    def get_allow_reviewer_invites(self):
        perm = '_Naaya___Invite_to_TalkBack_Consultation_Permission'
        roles = getattr(self, perm, [])
        return ('Reviewer' in roles)

    allow_reviewer_invites = property(get_allow_reviewer_invites,
                                      set_allow_reviewer_invites)

    security.declareProtected(PERMISSION_MANAGE_TALKBACKCONSULTATION,
                              'saveProperties')

    def saveProperties(self, REQUEST=None, **kwargs):
        """ """
        if not self.checkPermissionEditObject():
            raise EXCEPTION_NOTAUTHORIZED(EXCEPTION_NOTAUTHORIZED_MSG)

        if REQUEST is not None:
            schema_raw_data = dict(REQUEST.form)
        else:
            schema_raw_data = kwargs
        _lang = schema_raw_data.pop('_lang', schema_raw_data.pop('lang', None))
        _releasedate = self.process_releasedate(
            schema_raw_data.pop('releasedate', ''), self.releasedate)

        form_errors = self.process_submitted_form(
            schema_raw_data, _lang, _override_releasedate=_releasedate)

        if not form_errors:
            self._p_changed = True
            self.recatalogNyObject(self)
            # log date
            contributor = self.REQUEST.AUTHENTICATED_USER.getUserName()
            auth_tool = self.getAuthenticationTool()
            auth_tool.changeLastPost(contributor)
            notify(NyContentObjectEditEvent(self, contributor))
            if REQUEST:
                self.setSessionInfoTrans(MESSAGE_SAVEDCHANGES,
                                         date=self.utGetTodayDate())
                REQUEST.RESPONSE.redirect('%s/edit_html?lang=%s' %
                                          (self.absolute_url(), _lang))
        else:
            if REQUEST is not None:
                self._prepare_error_response(REQUEST, form_errors,
                                             schema_raw_data)
                REQUEST.RESPONSE.redirect('%s/edit_html?lang=%s' %
                                          (self.absolute_url(), _lang))
            else:
                raise ValueError(form_errors.popitem()[1])  # pick an error

    security.declareProtected(view, 'get_consultation')

    def get_consultation(self):
        return self

    security.declareProtected(view, 'list_sections')

    def list_sections(self):
        """ """
        metatypes = [METATYPE_TALKBACKCONSULTATION_SECTION]
        sections = dict(self.objectItems(metatypes))

        output = []
        for section_id in self.section_sort_order:
            if section_id in sections:
                output.append(sections.pop(section_id))

        output.extend(sorted(sections.values(),
                             key=operator.attrgetter('title')))

        return output

    security.declareProtected(PERMISSION_MANAGE_TALKBACKCONSULTATION,
                              'save_sort_order')

    def save_sort_order(self, sort_section_id, REQUEST=None):
        """ save the sort order of sections """
        self.section_sort_order = tuple(sort_section_id)
        if REQUEST is not None:
            REQUEST.RESPONSE.redirect(self.absolute_url())

    _comments_atom = NaayaPageTemplateFile('zpt/comments_atom', globals(),
                                           'tbconsultation_comments_atom')
    security.declareProtected(view, 'comments_atom')

    def comments_atom(self, REQUEST=None, days=2):
        """ ATOM feed with consultation comments """

        if isinstance(days, basestring):
            try:
                days = int(days)
            except:
                days = 2

        cutoff = DateTime() - days
        comments_list = []
        for section in self.list_sections():
            for paragraph in section.get_paragraphs():
                for comment in paragraph.get_comments():
                    if comment.comment_date < cutoff:
                        continue
                    comments_list.append(comment)
        comments_list.sort(key=operator.attrgetter('comment_date'),
                           reverse=True)

        if comments_list:
            feed_updated = comments_list[0].comment_date
        else:
            feed_updated = DateTime()

        def atom_date_format(date):
            d = DT2dt(date).strftime('%Y-%m-%dT%H:%M:%S%z')
            return d[:-2] + ':' + d[-2:]

        if REQUEST is not None:
            REQUEST.RESPONSE.setHeader('Content-Type', 'application/atom+xml')

        return self._comments_atom(comments_list=comments_list,
                                   atom_date_format=atom_date_format,
                                   feed_updated=feed_updated)

    security.declareProtected(view, 'get_start_date')

    def get_start_date(self):
        """ Returns the start date in dd/mm/yyyy string format. """

        return self.utConvertDateTimeObjToString(self.start_date)

    security.declareProtected(view, 'get_end_date')

    def get_end_date(self):
        """ Returns the end date in dd/mm/yyyy string format. """

        return self.utConvertDateTimeObjToString(self.end_date)

    security.declareProtected(view, 'get_days_left')

    def get_days_left(self):
        """ Returns the remaining days for the consultation
        or the number of days before it starts """
        today = self.utGetTodayDate().earliestTime()
        if not self.start_date or not self.end_date:
            return (1, 0)

        after_end_date = self.end_date + 1
        if self.start_date.lessThanEqualTo(today):
            return (1, int(str(after_end_date - today).split('.')[0]))
        else:
            return (0, int(str(self.start_date - today).split('.')[0]))

    security.declareProtected(view_management_screens, 'manage_options')

    def manage_options(self):
        """ """

        l_options = (NyContainer.manage_options[0],)
        l_options += ({'label': 'View', 'action': 'index_html'},) + \
            NyContainer.manage_options[3:8]
        return l_options

    security.declareProtected(PERMISSION_MANAGE_TALKBACKCONSULTATION,
                              'delete_sections')

    def delete_sections(self, del_section_id, REQUEST=None):
        """ remove the specified sections """
        self.manage_delObjects(list(del_section_id))
        self.setSessionInfoTrans('Removed ${count} sections.',
                                 count=str(len(del_section_id)))
        if REQUEST is not None:
            REQUEST.RESPONSE.redirect(self.absolute_url())

    def get_user_name(self):
        # first, check if we have an invite key
        invitation = self.invitations.get_current_invitation(self.REQUEST)
        if invitation is not None:
            return invitation.name

        # no invite key; look for current Zope user
        auth_tool = self.getAuthenticationTool()
        userid = auth_tool.get_current_userid()

        if userid is None:  # anonymous user
            return None

        name = auth_tool.name_from_userid(userid)
        if name == '':
            name = userid
        return name

    def get_user_name_or_userid(self, userid=None):
        if userid is None:
            return self.get_user_name()

        auth_tool = self.getAuthenticationTool()
        name = auth_tool.name_from_userid(userid)
        if name == '':
            name = userid

        return name

    def checkTalkBackConsultationUser(self):
        """
        Checks if the user is logged in and has reviewer rights:
        0 if user is anonymous,
        1 if user has reviewer role
        2 if user doesn't have reviewer role
        """
        review_check = self.checkPermissionReviewTalkBackConsultation()

        if self.isAnonymousUser():
            return 0
        elif review_check:
            return 1
        elif not review_check:
            return 2

    security.declareProtected(view, 'check_cannot_comment')

    def check_cannot_comment(self):
        """ """

        if not self.checkPermissionReviewTalkBackConsultation():
            if self.isAnonymousUser():
                return 'not-logged-in'
            else:
                return 'no-permission'

        if self.get_days_left()[1] <= 0 and not (
                self.checkPermissionManageTalkBackConsultation() or
                self.checkPermissionReviewTalkBackConsultationAfterDeadline()):
            return 'deadline-reached'

    security.declareProtected(
        PERMISSION_COMMENTS_ADD, 'log_in_authenticated')

    def log_in_authenticated(self, REQUEST=None):
        """ Log in user and redirect to TalkBack Consultation index """
        if REQUEST is not None:
            self.REQUEST.RESPONSE.redirect(self.absolute_url())

    # permissions
    def checkPermissionReviewTalkBackConsultation(self):
        """
        Check for reviewing the TalkBack Consultation.
        """
        return self.checkPermission(PERMISSION_REVIEW_TALKBACKCONSULTATION)

    security.declareProtected(
        PERMISSION_REVIEW_TALKBACKCONSULTATION_AFTER_DEADLINE,
        'review_after_deadline')

    def review_after_deadline(self):
        """
        Dummy function to register the permission.
        """
        raise NotImplementedError

    def checkPermissionReviewTalkBackConsultationAfterDeadline(self):
        """
        Check for reviewing the TalkBack Consultation
        after the deadline has passed.
        """
        return self.checkPermission(
            PERMISSION_REVIEW_TALKBACKCONSULTATION_AFTER_DEADLINE)

    def checkPermissionManageTalkBackConsultation(self):
        """
        Check for managing the TalkBack Consultation.
        """
        return self.checkPermission(PERMISSION_MANAGE_TALKBACKCONSULTATION)

    def checkPermissionInviteToTalkBackConsultation(self):
        """
        Check for inviting others to the TalkBack Consultation.
        """
        return self.checkPermission(PERMISSION_INVITE_TO_TALKBACKCONSULTATION)

    def own_comments(self):
        """
        Check if the current user has any comments on the consultation
        """
        return [comment for comment in self.admin_comments._all_comments()
                if comment['comment'].contributor ==
                self.REQUEST.AUTHENTICATED_USER.getUserName()]

    security.declareProtected(view, 'custom_editor')

    def custom_editor(self, editor_tool, lang, dom_id):
        extra_options = {
            'content_css':
                self.absolute_url() + '/misc_/NaayaContent/tb-editor.css',
            'theme_advanced_buttons1':
                'bold,italic,underline,strikethrough,sub,sup,forecolor,'
                'backcolor,removeformat,separator,'
                'bullist,numlist,separator,'
                'justifyleft,justifycenter,justifyright,justifyfull,separator,'
                'link,unlink,hr,image,separator,'
                'pastetext,pasteword,cleanup,code,help',
            'theme_advanced_buttons2': '',
        }
        return editor_tool.render(dom_id, lang, image_support=True,
                                  extra_options=extra_options)

    security.declareProtected(view, 'get_files')

    def get_files(self):
        """ Get a list of all files attached to the consultation"""
        return [ob for ob in self.objectValues('Naaya Blob File')]

    security.declareProtected(view, 'findUsers')

    def findUsers(self, search_param, search_term):
        """ """
        if len(search_term) == 0:
            return []
        return json.dumps(findUsers(self.getSite(), search_param, search_term))

    addSection = addSection

    # zmi pages
    security.declareProtected(view_management_screens, 'manage_edit_html')
    manage_edit_html = PageTemplateFile('zpt/talkbackconsultation_manage_edit',
                                        globals())

    # site pages
    security.declareProtected(view, 'index_html')
    index_html = NaayaPageTemplateFile('zpt/talkbackconsultation_index',
                                       globals(), 'tbconsultation_index')

    # standard_template_macro, header and footer templates are proxied
    # since invited reviewers have "View" permission only in this folder;
    # if the consultation is restricted, they would not be able to see
    # consultation pages.
    def standard_html_header(self, *args, **kwargs):
        return self.aq_parent.standard_html_header(*args, **kwargs)

    def standard_html_footer(self, *args, **kwargs):
        return self.aq_parent.standard_html_footer(*args, **kwargs)

    def standard_template_macro(self, *args, **kwargs):
        return self.aq_parent.standard_template_macro(*args, **kwargs)

    security.declareProtected(PERMISSION_MANAGE_TALKBACKCONSULTATION,
                              'edit_html')
    edit_html = NaayaPageTemplateFile('zpt/talkbackconsultation_edit',
                                      globals(), 'tbconsultation_edit')

    security.declareProtected(PERMISSION_MANAGE_TALKBACKCONSULTATION,
                              'section_add_html')
    section_add_html = addSection_html

    __allow_groups__ = InvitationUsersTool()
    _View_Permission = ['InvitedReviewer']
    _Naaya___Review_TalkBack_Consultation_Permission = ['InvitedReviewer']
    __ac_roles__ = ['InvitedReviewer']

    admin_comments = CommentsAdmin('admin_comments')
コード例 #4
0
class NyTalkBackConsultation(
    Implicit,
    NyContentData,
    NyContentType,
    NyAttributes,
    NyProperties,
    NyRoleManager,
    NyContainer,
    NyNonCheckControl,
    utils,
):
    """ """

    meta_type = METATYPE_TALKBACKCONSULTATION
    meta_label = LABEL_OBJECT

    meta_types = [
        {
            "name": METATYPE_TALKBACKCONSULTATION_SECTION,
            "action": "addSection",
            "permission": PERMISSION_MANAGE_TALKBACKCONSULTATION,
        }
    ]

    icon = "misc_/NaayaContent/NyTalkBackConsultation.gif"
    icon_marked = "misc_/NaayaContent/NyTalkBackConsultation_marked.gif"

    security = ClassSecurityInfo()

    edit_access = NyAccess(
        "edit_access",
        {
            PERMISSION_REVIEW_TALKBACKCONSULTATION: "Submit comments",
            PERMISSION_MANAGE_TALKBACKCONSULTATION: "Administer consultation",
            PERMISSION_INVITE_TO_TALKBACKCONSULTATION: "Send invitations",
        },
    )

    section_sort_order = tuple()

    def __init__(self, id, contributor):
        """ """
        self.id = id
        self.contributor = contributor
        NyContainer.__dict__["__init__"](self)
        NyProperties.__dict__["__init__"](self)
        self.invitations = InvitationsContainer("invitations")
        self.submitted = 1

    def set_allow_reviewer_invites(self, allow):
        perm = "_Naaya___Invite_to_TalkBack_Consultation_Permission"
        roles = getattr(self, perm, [])

        if allow and "Reviewer" not in roles:
            roles.append("Reviewer")
        elif not allow and "Reviewer" in roles:
            roles.remove("Reviewer")

        if roles:
            setattr(self, perm, roles)
        else:
            if hasattr(self, perm):
                delattr(self, perm)

    def get_allow_reviewer_invites(self):
        perm = "_Naaya___Invite_to_TalkBack_Consultation_Permission"
        roles = getattr(self, perm, [])
        return "Reviewer" in roles

    allow_reviewer_invites = property(get_allow_reviewer_invites, set_allow_reviewer_invites)

    security.declareProtected(PERMISSION_MANAGE_TALKBACKCONSULTATION, "saveProperties")

    def saveProperties(self, REQUEST=None, **kwargs):
        """ """
        if not self.checkPermissionEditObject():
            raise EXCEPTION_NOTAUTHORIZED, EXCEPTION_NOTAUTHORIZED_MSG

        if REQUEST is not None:
            schema_raw_data = dict(REQUEST.form)
        else:
            schema_raw_data = kwargs
        _lang = schema_raw_data.pop("_lang", schema_raw_data.pop("lang", None))
        _releasedate = self.process_releasedate(schema_raw_data.pop("releasedate", ""), self.releasedate)

        form_errors = self.process_submitted_form(schema_raw_data, _lang, _override_releasedate=_releasedate)

        if not form_errors:
            self._p_changed = True
            self.recatalogNyObject(self)
            # log date
            contributor = self.REQUEST.AUTHENTICATED_USER.getUserName()
            auth_tool = self.getAuthenticationTool()
            auth_tool.changeLastPost(contributor)
            notify(NyContentObjectEditEvent(self, contributor))
            if REQUEST:
                self.setSessionInfoTrans(MESSAGE_SAVEDCHANGES, date=self.utGetTodayDate())
                REQUEST.RESPONSE.redirect("%s/edit_html?lang=%s" % (self.absolute_url(), _lang))
        else:
            if REQUEST is not None:
                self._prepare_error_response(REQUEST, form_errors, schema_raw_data)
                REQUEST.RESPONSE.redirect("%s/edit_html?lang=%s" % (self.absolute_url(), _lang))
            else:
                raise ValueError(form_errors.popitem()[1])  # pick a random error

    security.declareProtected(view, "get_consultation")

    def get_consultation(self):
        return self

    security.declareProtected(view, "list_sections")

    def list_sections(self):
        """ """
        metatypes = [METATYPE_TALKBACKCONSULTATION_SECTION]
        sections = dict(self.objectItems(metatypes))

        output = []
        for section_id in self.section_sort_order:
            if section_id in sections:
                output.append(sections.pop(section_id))

        output.extend(sorted(sections.values(), key=operator.attrgetter("title")))

        return output

    security.declareProtected(PERMISSION_MANAGE_TALKBACKCONSULTATION, "save_sort_order")

    def save_sort_order(self, sort_section_id, REQUEST=None):
        """ save the sort order of sections """
        self.section_sort_order = tuple(sort_section_id)
        if REQUEST is not None:
            REQUEST.RESPONSE.redirect(self.absolute_url())

    _comments_atom = NaayaPageTemplateFile("zpt/comments_atom", globals(), "tbconsultation_comments_atom")
    security.declareProtected(view, "comments_atom")

    def comments_atom(self, REQUEST=None, days=2):
        """ ATOM feed with consultation comments """

        if isinstance(days, basestring):
            try:
                days = int(days)
            except:
                days = 2

        cutoff = DateTime() - days
        comments_list = []
        for section in self.list_sections():
            for paragraph in section.get_paragraphs():
                for comment in paragraph.get_comments():
                    if comment.comment_date < cutoff:
                        continue
                    comments_list.append(comment)
        comments_list.sort(key=operator.attrgetter("comment_date"), reverse=True)

        if comments_list:
            feed_updated = comments_list[0].comment_date
        else:
            feed_updated = DateTime()

        def atom_date_format(date):
            d = DT2dt(date).strftime("%Y-%m-%dT%H:%M:%S%z")
            return d[:-2] + ":" + d[-2:]

        if REQUEST is not None:
            REQUEST.RESPONSE.setHeader("Content-Type", "application/atom+xml")

        return self._comments_atom(
            comments_list=comments_list, atom_date_format=atom_date_format, feed_updated=feed_updated
        )

    security.declareProtected(view, "get_start_date")

    def get_start_date(self):
        """ Returns the start date in dd/mm/yyyy string format. """

        return self.utConvertDateTimeObjToString(self.start_date)

    security.declareProtected(view, "get_end_date")

    def get_end_date(self):
        """ Returns the end date in dd/mm/yyyy string format. """

        return self.utConvertDateTimeObjToString(self.end_date)

    security.declareProtected(view, "get_days_left")

    def get_days_left(self):
        """ Returns the remaining days for the consultation or the number of days before it starts """
        today = self.utGetTodayDate().earliestTime()
        if not self.start_date or not self.end_date:
            return (1, 0)

        after_end_date = self.end_date + 1
        if self.start_date.lessThanEqualTo(today):
            return (1, int(str(after_end_date - today).split(".")[0]))
        else:
            return (0, int(str(self.start_date - today).split(".")[0]))

    security.declareProtected(view_management_screens, "manage_options")

    def manage_options(self):
        """ """

        l_options = (NyContainer.manage_options[0],)
        l_options += ({"label": "View", "action": "index_html"},) + NyContainer.manage_options[3:8]
        return l_options

    security.declareProtected(PERMISSION_MANAGE_TALKBACKCONSULTATION, "delete_sections")

    def delete_sections(self, del_section_id, REQUEST=None):
        """ remove the specified sections """
        self.manage_delObjects(list(del_section_id))
        self.setSessionInfoTrans("Removed ${count} sections.", count=str(len(del_section_id)))
        if REQUEST is not None:
            REQUEST.RESPONSE.redirect(self.absolute_url())

    def get_user_name(self):
        # first, check if we have an invite key
        invitation = self.invitations.get_current_invitation(self.REQUEST)
        if invitation is not None:
            return invitation.name

        # no invite key; look for current Zope user
        auth_tool = self.getAuthenticationTool()
        userid = auth_tool.get_current_userid()

        if userid is None:  # anonymous user
            return None

        name = auth_tool.name_from_userid(userid)
        if name == "":
            name = userid
        return name

    def get_user_name_or_userid(self, userid=None):
        if userid is None:
            return self.get_user_name()

        auth_tool = self.getAuthenticationTool()
        name = auth_tool.name_from_userid(userid)
        if name == "":
            name = userid

        return name

    def checkTalkBackConsultationUser(self):
        """
        Checks if the user is logged in and has reviewer rights:
        0 if user is anonymous,
        1 if user has reviewer role
        2 if user doesn't have reviewer role
        """
        review_check = self.checkPermissionReviewTalkBackConsultation()

        if self.isAnonymousUser():
            return 0
        elif review_check:
            return 1
        elif not review_check:
            return 2

    security.declareProtected(view, "check_cannot_comment")

    def check_cannot_comment(self):
        """ """

        if not self.checkPermissionReviewTalkBackConsultation():
            if self.isAnonymousUser():
                return "not-logged-in"
            else:
                return "no-permission"

        if self.get_days_left()[1] <= 0 and not (
            self.checkPermissionManageTalkBackConsultation()
            or self.checkPermissionReviewTalkBackConsultationAfterDeadline()
        ):
            return "deadline-reached"

    security.declareProtected(PERMISSION_COMMENTS_ADD, "log_in_authenticated")

    def log_in_authenticated(self, REQUEST=None):
        """ Log in user and redirect to TalkBack Consultation index """
        if REQUEST is not None:
            self.REQUEST.RESPONSE.redirect(self.absolute_url())

    # permissions
    def checkPermissionReviewTalkBackConsultation(self):
        """
        Check for reviewing the TalkBack Consultation.
        """
        return self.checkPermission(PERMISSION_REVIEW_TALKBACKCONSULTATION)

    security.declareProtected(PERMISSION_REVIEW_TALKBACKCONSULTATION_AFTER_DEADLINE, "review_after_deadline")

    def review_after_deadline(self):
        """
        Dummy function to register the permission.
        """
        raise NotImplementedError

    def checkPermissionReviewTalkBackConsultationAfterDeadline(self):
        """
        Check for reviewing the TalkBack Consultation
        after the deadline has passed.
        """
        return self.checkPermission(PERMISSION_REVIEW_TALKBACKCONSULTATION_AFTER_DEADLINE)

    def checkPermissionManageTalkBackConsultation(self):
        """
        Check for managing the TalkBack Consultation.
        """
        return self.checkPermission(PERMISSION_MANAGE_TALKBACKCONSULTATION)

    def checkPermissionInviteToTalkBackConsultation(self):
        """
        Check for inviting others to the TalkBack Consultation.
        """
        return self.checkPermission(PERMISSION_INVITE_TO_TALKBACKCONSULTATION)

    security.declareProtected(view, "custom_editor")

    def custom_editor(self, editor_tool, lang, dom_id):
        extra_options = {
            "content_css": self.absolute_url() + "/misc_/NaayaContent/tb-editor.css",
            "theme_advanced_buttons1": "bold,italic,underline,strikethrough,sub,sup,forecolor,"
            "backcolor,removeformat,separator,"
            "bullist,numlist,separator,"
            "justifyleft,justifycenter,justifyright,justifyfull,separator,"
            "link,unlink,hr,image,separator,"
            "pastetext,pasteword,cleanup,code,help",
            "theme_advanced_buttons2": "",
        }
        return editor_tool.render(dom_id, lang, image_support=True, extra_options=extra_options)

    addSection = addSection

    # zmi pages
    security.declareProtected(view_management_screens, "manage_edit_html")
    manage_edit_html = PageTemplateFile("zpt/talkbackconsultation_manage_edit", globals())

    # site pages
    security.declareProtected(view, "index_html")
    index_html = NaayaPageTemplateFile("zpt/talkbackconsultation_index", globals(), "tbconsultation_index")

    # standard_template_macro, header and footer templates are proxied
    # since invited reviewers have "View" permission only in this folder;
    # if the consultation is restricted, they would not be able to see
    # consultation pages.
    def standard_html_header(self, *args, **kwargs):
        return self.aq_parent.standard_html_header(*args, **kwargs)

    def standard_html_footer(self, *args, **kwargs):
        return self.aq_parent.standard_html_footer(*args, **kwargs)

    def standard_template_macro(self, *args, **kwargs):
        return self.aq_parent.standard_template_macro(*args, **kwargs)

    security.declareProtected(PERMISSION_MANAGE_TALKBACKCONSULTATION, "edit_html")
    edit_html = NaayaPageTemplateFile("zpt/talkbackconsultation_edit", globals(), "tbconsultation_edit")

    security.declareProtected(PERMISSION_MANAGE_TALKBACKCONSULTATION, "section_add_html")
    section_add_html = addSection_html

    __allow_groups__ = InvitationUsersTool()
    _View_Permission = ["InvitedReviewer"]
    _Naaya___Review_TalkBack_Consultation_Permission = ["InvitedReviewer"]
    __ac_roles__ = ["InvitedReviewer"]

    admin_comments = CommentsAdmin("admin_comments")