Exemplo n.º 1
0
    def setUp(self):
        super(NyAccess2LevelTestCase, self).setUp()

        self.perm1, self.perm2 = 'View', 'View History'
        self.role1, self.role2 = 'Contributor', 'Reviewer'

        addNyFolder(self.portal.info,
                    'testfolderparent',
                    contributor='admin',
                    submission=1)
        self.testfolderparent = self.portal.info.testfolderparent

        addNyFolder(self.testfolderparent,
                    'testfolder',
                    contributor='admin',
                    submission=1)
        self.testfolder = self.testfolderparent.testfolder

        # NOTE: this is *not* the way to use NyAccess. It should never
        # be stored in the database. It should be set as an attribute
        # to a *class*, like NyForum.
        self.testfolderparent._setOb(
            'ny_access',
            NyAccess('ny_access', {
                self.perm1: self.perm1,
                self.perm2: self.perm2
            }))

        self.testfolder._setOb(
            'ny_access',
            NyAccess('ny_access', {
                self.perm1: self.perm1,
                self.perm2: self.perm2
            }))

        # default permission map
        # parent folder does not inherit permissions
        permission = Permission(self.perm1, (), self.testfolderparent)
        permission.setRoles((self.role1, 'Manager'))
        permission = Permission(self.perm2, (), self.testfolderparent)
        permission.setRoles((self.role2, 'Manager'))
        # child folder permissions
        permission = Permission(self.perm1, (), self.testfolder)
        permission.setRoles([self.role2])
        permission = Permission(self.perm2, (), self.testfolder)
        permission.setRoles((self.role1, 'Manager'))

        transaction.commit()
Exemplo n.º 2
0
    def setUp(self):
        super(NyAccessTestCase, self).setUp()

        addNyFolder(self.portal.info,
                    'testfolder',
                    contributor='admin',
                    submission=1)
        self.testfolder = self.portal.info.testfolder

        # NOTE: this is *not* the way to use NyAccess. It should never
        # be stored in the database. It should be set as an attribute
        # to a *class*, like NyForum.
        self.testfolder._setOb(
            'ny_access',
            NyAccess('ny_access', {
                'View': 'View',
                'View History': 'View History'
            }))

        transaction.commit()
Exemplo n.º 3
0
class MegaSurvey(SurveyQuestionnaire, BaseSurveyTemplate):
    """ """

    meta_type = 'Naaya Mega Survey'
    meta_label = 'Survey'

    _constructors = (manage_addMegaSurvey, )

    security = ClassSecurityInfo()

    edit_access = NyAccess(
        'edit_access', {
            PERMISSION_ADD_ANSWER: "Submit answer",
            PERMISSION_ADD_REPORT: "Create report",
            PERMISSION_ADD_ATTACHMENT: "Attach file",
            PERMISSION_VIEW_ANSWERS: "View answers",
            PERMISSION_EDIT_ANSWERS: "Edit answers",
            PERMISSION_VIEW_REPORTS: "View reports",
        })

    def __init__(self, id, **kwargs):
        """ """
        # BaseSurveyTemplate.__init__(self, id, **kwargs)
        SurveyQuestionnaire.__init__(self, id, None, **kwargs)
        self.contributor = kwargs.get('contributor')
        self.approved = 1

    def can_be_seen(self):
        """
        Indicates if the current user has access to the current folder.

        """
        return self.checkPermission(view)

    def all_meta_types(self, interfaces=None):
        """What can you put inside me?"""
        return BaseSurveyTemplate.all_meta_types(self, interfaces)

    def getSurveyTemplate(self):
        """ """
        return self

    security.declareProtected(view, 'download')

    def download(self, REQUEST=None, RESPONSE=None):
        """returns all the answers in a csv file"""
        def stringify(value):
            if not isinstance(value, basestring):
                value = unicode(value)
            if isinstance(value, str):
                return unicode(value, 'utf-8')
            return value

        def all_stringify(row):
            return [stringify(value) for value in row]

        answers = self.getAnswers()
        widgets = self.getSortedWidgets()
        header = ['Respondent']
        for widget in widgets:
            header += [widget.title_or_id()]
            if widget.meta_type == 'Naaya Radio Matrix Widget':
                header += widget.rows
        rows = [answer.answer_values() for answer in answers]
        rows = [all_stringify(item) for item in rows]

        file_type = REQUEST.get('file_type', 'CSV')
        if file_type == 'CSV':
            RESPONSE.setHeader('Content-Type', 'text/csv')
            RESPONSE.setHeader('Content-Disposition',
                               'attachment; filename=%s.csv' % self.id)
            return generate_csv(header, rows)
        if file_type == 'Excel' and self.rstk.we_provide('Excel export'):
            RESPONSE.setHeader('Content-Type', 'application/vnd.ms-excel')
            RESPONSE.setHeader('Content-Disposition',
                               'attachment; filename=%s.xls' % self.id)
            return generate_excel(header, rows)
        else:
            raise ValueError('unknown file format %r' % file_type)

    #
    # Site pages
    #
    security.declareProtected(view, 'index_html')

    def index_html(self):
        """ """
        if (not self.checkPermissionSkipCaptcha()
                and not self.recaptcha_is_present()):
            raise ValueError("Invalid recaptcha keys")
        return self._index_html()

    _index_html = NaayaPageTemplateFile('zpt/megasurvey_index', globals(),
                                        'NaayaSurvey.megasurvey_index')

    security.declareProtected(PERMISSION_EDIT_OBJECTS, 'edit_html')
    edit_html = NaayaPageTemplateFile('zpt/megasurvey_edit', globals(),
                                      'NaayaSurvey.megasurvey_edit')

    security.declareProtected(PERMISSION_EDIT_OBJECTS, 'edit_attachments_html')
    edit_attachments_html = NaayaPageTemplateFile(
        'zpt/megasurvey_edit_attachments', globals(),
        'NaayaSurvey.megasurvey_edit_attachments')

    security.declareProtected(PERMISSION_EDIT_OBJECTS, 'edit_questions_html')
    edit_questions_html = NaayaPageTemplateFile(
        'zpt/megasurvey_edit_questions', globals(),
        'NaayaSurvey.megasurvey_edit_questions')

    security.declareProtected(PERMISSION_EDIT_OBJECTS, 'edit_reports_html')
    edit_reports_html = NaayaPageTemplateFile(
        'zpt/megasurvey_edit_reports', globals(),
        'NaayaSurvey.megasurvey_edit_reports')

    #
    # change the security of the inherited methods
    #
    security.declareProtected(PERMISSION_EDIT_OBJECTS, 'saveProperties')
    security.declareProtected(PERMISSION_EDIT_OBJECTS, 'addWidget')
    security.declareProtected(PERMISSION_EDIT_OBJECTS, 'deleteItems')
    security.declareProtected(PERMISSION_EDIT_OBJECTS, 'setSortOrder')
    security.declareProtected(PERMISSION_EDIT_OBJECTS, 'addReport')
    security.declareProtected(PERMISSION_EDIT_OBJECTS, 'generateFullReport')
    security.declareProtected(PERMISSION_EDIT_OBJECTS, 'addAttachment')

    # static files
    css_survey_common = DTMLFile('www/survey_common.css', globals())
    css_survey_print = DTMLFile('www/survey_print.css', globals())
    fancy_checkmark = ImageFile('www/fancy_checkmark.gif', globals())
    survey_js = ImageFile('www/survey.js', globals())

    security.declareProtected(PERMISSION_EDIT_ANSWERS, 'bogus')

    def bogus(self):
        """ Needed in Naaya Access. It is mandatory that a permission must be
        declared so it can be used in Naaya Access.
        This should be removed once this issue is solved

        """
        pass

    security.declarePublic('display_admin_warning')

    def display_admin_warning(self):
        return self.checkPermissionPublishObjects()\
            and self.anonymous_has_access()\
            and not self.recaptcha_is_present()\
            and not self.anonymous_skips_captcha()

    security.declarePublic('anonymous_has_access')

    def anonymous_has_access(self):
        return 'Anonymous' in self.edit_access.getPermissionMapping(
        )['Naaya - Add Naaya Survey Answer']

    security.declarePublic('anonymous_skips_captcha')

    def anonymous_skips_captcha(self):
        permission = 'Naaya - Skip Captcha'
        permission_object = Permission(permission, (), self)
        return 'Anonymous' in permission_object.getRoles()

    security.declarePrivate('dont_inherit_view_permission')

    def dont_inherit_view_permission(self):
        permission = Permission(view, (), self)
        roles = permission.getRoles()
        roles = tuple(set(roles) | set(['Manager', 'Administrator', 'Owner']))
        permission.setRoles(roles)

    security.declarePrivate('inherit_view_permission')

    def inherit_view_permission(self):
        permission = Permission(view, (), self)
        roles = permission.getRoles()
        roles = list(roles)
        permission.setRoles(roles)
Exemplo n.º 4
0
class NyConsultation(NyAttributes, Implicit, NyProperties, BTreeFolder2,
                     NyContainer, NyCheckControl, NyValidation, utils):
    """ """

    meta_type = METATYPE_OBJECT
    meta_label = LABEL_OBJECT

    all_meta_types = ()

    icon = 'misc_/NaayaContent/NyConsultation.gif'
    icon_marked = 'misc_/NaayaContent/NyConsultation_marked.gif'

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

    security = ClassSecurityInfo()

    edit_access = NyAccess(
        'edit_access', {
            PERMISSION_REVIEW_CONSULTATION: "Submit comments",
            PERMISSION_VIEW_CONSULTATION: "View consultation",
            PERMISSION_MANAGE_CONSULTATION: "Administer consultation",
        })

    def __init__(self, id, title, description, sortorder, start_date, end_date,
                 public_registration, allow_file, line_comments, contributor,
                 releasedate, lang):
        """ """
        self.id = id
        NyValidation.__dict__['__init__'](self)
        NyCheckControl.__dict__['__init__'](self)
        NyContainer.__dict__['__init__'](self)
        BTreeFolder2.__init__(self)
        self.contributor = contributor
        self.questions = {}
        try:
            del self.title
        except:
            pass
        self.save_properties(title, description, sortorder, start_date,
                             end_date, public_registration, allow_file,
                             line_comments, releasedate, lang)
        NyProperties.__dict__['__init__'](self)
        self.submitted = 1

    security.declarePrivate('save_properties')

    def save_properties(self, title, description, sortorder, start_date,
                        end_date, public_registration, allow_file,
                        line_comments, 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()

        self.sortorder = sortorder
        self.releasedate = releasedate
        self.public_registration = public_registration
        self.allow_file = allow_file
        self.line_comments = line_comments

    security.declareProtected(PERMISSION_MANAGE_CONSULTATION, 'saveProperties')

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

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

        if file and not file.read():
            self.setSession('title', title)
            self.setSession('description', description)
            self.setSessionErrors(['File must not be empty'])
            return REQUEST.RESPONSE.redirect('%s/edit_html?lang=%s' %
                                             (self.absolute_url(), lang))

        exfile = self.get_exfile()

        if file and exfile:
            exfile.saveUpload(file=file, lang=lang)
            downloadfilename = file.filename
            exfile._setLocalPropValue('downloadfilename', lang,
                                      downloadfilename)
        elif file and not exfile:
            addNyExFile(self, title=title, file=file, lang=lang, source='file')

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

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

    security.declareProtected(PERMISSION_MANAGE_CONSULTATION,
                              'updateRequestRoleStatus')

    def updateRequestRoleStatus(self, public_registration, lang):
        if public_registration:
            self.updateDynamicProperties(
                self.processDynamicProperties(
                    METATYPE_OBJECT, {'show_contributor_request_role': 'on'}),
                lang)
        if not public_registration:
            self.updateDynamicProperties(
                self.processDynamicProperties(
                    METATYPE_OBJECT, {'show_contributor_request_role': ''}),
                lang)

    security.declareProtected(PERMISSION_MANAGE_CONSULTATION,
                              '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 'Reviewer' not in roles:
            auth_tool.addRole('Reviewer', [PERMISSION_REVIEW_CONSULTATION])
        else:
            permission_add_role(self, PERMISSION_REVIEW_CONSULTATION,
                                'Reviewer')

        #give permissions to administrators
        admin_permissions = self.permissionsOfRole('Administrator')
        site = self.getSite()
        if PERMISSION_MANAGE_CONSULTATION not in admin_permissions:
            site.manage_permission(PERMISSION_MANAGE_CONSULTATION,
                                   ('Administrator', ),
                                   acquire=1)
            site.manage_permission(PERMISSION_VIEW_CONSULTATION,
                                   ('Administrator', ),
                                   acquire=1)
            site.manage_permission(PERMISSION_REVIEW_CONSULTATION,
                                   ('Administrator', ),
                                   acquire=1)

    ########################
    # Rate lists
    ########################
    manage_addRateList = manage_addRateList

    security.declareProtected(PERMISSION_MANAGE_CONSULTATION, 'default_rating')

    def default_rating(self):
        self.admin_addratelist('Relevancy', 'Relevancy', 'Relevancy')
        self.admin_additem('Relevancy', '1', 'Less relevant')
        self.admin_additem('Relevancy', '2', 'Average relevant')
        self.admin_additem('Relevancy', '3', 'Very relevant')

    security.declareProtected(PERMISSION_MANAGE_CONSULTATION, 'getRateValue')

    def getRateValue(self, review, rate):
        """ """
        try:
            return review.ratings[rate.title]
        except:
            return None

    security.declareProtected(PERMISSION_MANAGE_CONSULTATION, 'getRateLists')

    def getRateLists(self):
        return self.objectValues('Rate Item')

    security.declareProtected(PERMISSION_MANAGE_CONSULTATION,
                              'getRateListById')

    def getRateListById(self, p_id):
        #return the selection list with the given id
        try:
            ob = self._getOb(p_id)
        except:
            ob = None
        if ob is not None:
            if ob.meta_type != 'Rate Item': ob = None
        return ob

    security.declareProtected(PERMISSION_MANAGE_CONSULTATION,
                              'admin_deleteratelist')

    def admin_deleteratelist(self, ids=[], REQUEST=None):
        """ """
        self.manage_delObjects(self.utConvertToList(ids))
        if REQUEST:
            self.setSessionInfoTrans(MESSAGE_SAVEDCHANGES,
                                     date=self.utGetTodayDate())
            REQUEST.RESPONSE.redirect('%s/admin_ratelists_html' %
                                      self.absolute_url())

    security.declareProtected(PERMISSION_MANAGE_CONSULTATION,
                              'admin_addratelist')

    def admin_addratelist(self, id='', title='', description='', REQUEST=None):
        """ """
        self.manage_addRateList(id, title, description)
        if REQUEST:
            self.setSessionInfoTrans(MESSAGE_SAVEDCHANGES,
                                     date=self.utGetTodayDate())
            REQUEST.RESPONSE.redirect('%s/admin_ratelists_html' %
                                      self.absolute_url())

    security.declareProtected(PERMISSION_MANAGE_CONSULTATION,
                              'admin_editratelist')

    def admin_editratelist(self,
                           id='',
                           title='',
                           description='',
                           REQUEST=None):
        """ """
        ob = self.getRateListById(id)
        if ob is not None:
            ob.manageProperties(title, description)
        if REQUEST:
            self.setSessionInfoTrans(MESSAGE_SAVEDCHANGES,
                                     date=self.utGetTodayDate())
            REQUEST.RESPONSE.redirect('%s/admin_ratelist_html?id=%s' %
                                      (self.absolute_url(), id))

    security.declareProtected(PERMISSION_MANAGE_CONSULTATION,
                              'admin_deleteitems')

    def admin_deleteitems(self, id='', ids=[], REQUEST=None):
        """ """
        ob = self.getRateListById(id)
        if ob is not None:
            ob.manage_delete_items(self.utConvertToList(ids))
        if REQUEST:
            self.setSessionInfoTrans(MESSAGE_SAVEDCHANGES,
                                     date=self.utGetTodayDate())
            REQUEST.RESPONSE.redirect('%s/admin_ratelist_html?id=%s' %
                                      (self.absolute_url(), id))

    security.declareProtected(PERMISSION_MANAGE_CONSULTATION, 'admin_additem')

    def admin_additem(self, id='', item='', title='', REQUEST=None):
        """ """
        ob = self.getRateListById(id)
        if ob is not None:
            ob.manage_add_item(item, title)
        if REQUEST:
            self.setSessionInfoTrans(MESSAGE_SAVEDCHANGES,
                                     date=self.utGetTodayDate())
            REQUEST.RESPONSE.redirect('%s/admin_ratelist_html?id=%s' %
                                      (self.absolute_url(), id))

    security.declareProtected(view, 'get_consultation')

    def get_consultation(self):
        """ Returns this object"""
        return self

    security.declareProtected(view, 'get_consultation_url')

    def get_consultation_url(self):
        """ Returns this object's url"""
        return self.absolute_url()

    security.declareProtected(view, 'get_exfile')

    def get_exfile(self):
        """ Returns the first ExFile in the Consultation, there should be only one. """

        try:
            exfile = self.objectValues(['Naaya Extended File'])[0]
        except IndexError:
            exfile = None

        return exfile

    security.declareProtected(view, 'get_exfile_url')

    def get_exfile_url(self, lang):
        """ Returns the exfile download url for the given language """
        try:
            return self.get_exfile().getEditDownloadUrl(lang)
        except:
            return '[no_file]'

    security.declareProtected(view, 'check_exfile_for_lang')

    def check_exfile_for_lang(self, lang):
        """ Checks if there is a file uploaded for the given language. """

        return self.get_exfile().getFileItem(lang).size > 0

    security.declareProtected(view, 'get_exfile_langs')

    def get_exfile_langs(self):
        """ Returns the languages for witch NyExFile contains files. """

        return [
            language for language in self.getSite().gl_get_languages_map()
            if self.check_exfile_for_lang(language['id'])
        ]

    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 self.start_date.lessThanEqualTo(today):
            return (1, int(str((self.end_date + 1) - 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(view, 'check_contributor_review')

    def check_contributor_review(self, contributor='', REQUEST=None):
        """ Returns True if user already posted a comment """

        if not contributor and REQUEST:
            contributor = REQUEST.AUTHENTICATED_USER.getUserName()

        return contributor in [
            review.contributor
            for review in self.objectValues(['Consultation Review'])
        ]

    security.declareProtected(PERMISSION_REVIEW_CONSULTATION,
                              'addConsultationReview')

    def addConsultationReview(self,
                              contributor_name='',
                              file='',
                              REQUEST=None,
                              **kwargs):
        """ """

        contributor = REQUEST.AUTHENTICATED_USER.getUserName()

        if not contributor_name:
            self.setSession('contributor_name', contributor_name)
            self.setSessionErrors(['Fill in the name field.'])
            return REQUEST.RESPONSE.redirect(self.absolute_url() +
                                             '/review_add_html')

        if REQUEST:
            kwargs.update(REQUEST.form)

        if self.allow_file != '1':
            file = ''

        if self.line_comments != '1':
            kwargs['adt_comment'] = {}

        days = self.get_days_left()
        if days[0] == 1 and days[1] > 0 and self.get_exfile():
            if not self.check_contributor_review(contributor):
                addConsultationReviewItem(self, contributor, contributor_name,
                                          file, kwargs)
                return REQUEST.RESPONSE.redirect(self.absolute_url() +
                                                 '/review_add_html?status=ok')
            else:
                return REQUEST.RESPONSE.redirect(
                    self.absolute_url() + '/review_add_html?status=failed')
        elif days[0] == 1 and days[1] <= 0:
            return REQUEST.RESPONSE.redirect(self.absolute_url() +
                                             '/review_add_html?status=late')
        elif days[0] <= 0:
            return REQUEST.RESPONSE.redirect(self.absolute_url() +
                                             '/review_add_html?status=soon')
        else:
            return REQUEST.RESPONSE.redirect(self.absolute_url())

    def checkConsultationUser(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.checkPermissionReviewConsultation()

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

    def checkPermissionReviewConsultation(self):
        """
        Check for reviewing the Consultation.
        """
        return self.checkPermission(PERMISSION_REVIEW_CONSULTATION)

    def checkPermissionManageConsultation(self):
        """
        Check for managing the Consultation.
        """
        return self.checkPermission(PERMISSION_MANAGE_CONSULTATION)

    def checkPermissionViewConsultation(self):
        """
        Check for managing the Consultation.
        """
        return self.checkPermission(PERMISSION_VIEW_CONSULTATION)

    security.declareProtected(view, 'get_reviews')

    def get_reviews(self):
        """ Returns a list with all the Consultation Review objects """
        return self.objectValues(['Consultation Review'])

    def count_line_comments(self):
        """ Returns the total count of line comments in all reviews """

        reviews = self.get_reviews()
        count = 0
        if reviews:
            for review in reviews:
                if self.review_has_comments(review):
                    count = count + 1
        return count

    def count_additional_files(self):
        """ Returns the total count of additional files in all reviews """

        reviews = self.get_reviews()
        count = 0
        if reviews:
            for review in reviews:
                if review.size > 0:
                    count = count + 1
        return count

    def count_question_answers(self):
        """ Returns (question_id, answer_count) """

        reviews = self.get_reviews()
        questions = self.get_questions()
        count = {}

        for qid, q in questions:
            count[qid] = 0

        for review in reviews:
            for qid, answer in review.answers:
                if answer:
                    count[qid] = count[qid] + 1
        return count.items()

    security.declareProtected(PERMISSION_MANAGE_CONSULTATION, 'addQuestion')

    def addQuestion(self, question_body, lang, sortorder, REQUEST=None):
        """ """
        id = 'q%s' % self.utGenRandomId(4)

        try:
            sortorder = int(sortorder)
        except:
            sortorder = 100

        if not self.questions.has_key(id): id = id
        else: id = id + self.utGenRandomId()

        self.questions[id] = question_item(question_body, lang, sortorder)
        self._p_changed = 1
        return REQUEST.RESPONSE.redirect('%s/manage_questions_html' %
                                         (self.absolute_url(), ))

    security.declareProtected(PERMISSION_MANAGE_CONSULTATION,
                              'delete_question')

    def delete_question(self, qid, REQUEST=None):
        """ """
        del (self.questions[qid])
        self._p_changed = 1
        return REQUEST.RESPONSE.redirect('%s/manage_questions_html' %
                                         (self.absolute_url(), ))

    security.declareProtected(PERMISSION_MANAGE_CONSULTATION, 'edit_question')

    def edit_question(self, qid, question_body, lang, REQUEST=None):
        """ """
        self.questions[qid].save_properties(question_body, lang)
        self._p_changed = 1
        return REQUEST.RESPONSE.redirect('%s/question_edit_html?qid=%s' %
                                         (self.absolute_url(), qid))

    security.declareProtected(PERMISSION_REVIEW_CONSULTATION, 'get_questions')

    def get_questions(self):
        """ Returns the questions sorted by sortorder (question_id, question_item)"""
        question_items = self.questions.items()
        question_items.sort(lambda x, y: cmp(x[1].sortorder, y[1].sortorder))
        return question_items

    security.declareProtected(PERMISSION_MANAGE_CONSULTATION,
                              'getQuestionById')

    def getQuestionById(self, qid):
        """ Returns the question item for the given id"""
        return self.questions[qid]

    security.declareProtected(PERMISSION_MANAGE_CONSULTATION,
                              'changeSortorder')

    def changeSortorder(self, qid, sortorder):
        """ """
        self.getQuestionById(qid).set_sortorder(sortorder)
        self._p_changed = 1

    security.declareProtected(view, 'getQuestionBody')

    def getQuestionBody(self, qid, lang):
        """ Returns the question's body string for the specified language """
        return self.getQuestionById(qid).get_body(lang)

    security.declareProtected(view, 'getQuestionSortorder')

    def getQuestionSortorder(self, qid):
        """ """
        return self.getQuestionById(qid).get_sortorder()

    security.declareProtected(view, 'review_has_comments')

    def review_has_comments(self, review):
        """ Checks if the review has any line comments """
        try:
            return review.linecomments[0]['comment']
        except KeyError:
            return ''

    security.declareProtected(PERMISSION_MANAGE_CONSULTATION, 'comment_image')
    comment_image = ImageFile('www/consultation-comment.gif', globals())

    #Consultation statistics

    security.declareProtected(view, 'getRatingTitles')

    def getRatingTitles(self):
        """ """
        cns_ratings = [x.title for x in self.getRateLists()]
        return cns_ratings

    security.declareProtected(view, 'getQuestionsReviews')

    def getQuestionsReviews(self):
        """
        Returns a dictionary with question ids as keys and
        a list of reviews that answered to that question as values.
        {qid: [rating1, rating2, ]}
        """

        reviews = self.get_reviews()
        questions = self.get_questions()
        qs_rev = {}

        for qid, q in questions:
            qs_rev[qid] = []

        for review in reviews:
            for qid, answer in review.answers:
                if answer:
                    qs_rev[qid].append(review.getId())
        return qs_rev

    security.declareProtected(PERMISSION_VIEW_CONSULTATION, 'getReviewById')

    def getReviewById(self, rid):
        """ """
        reviews = self.get_reviews()
        for review in reviews:
            if review.getId() == rid:
                return review

    #reviews sorting
    security.declareProtected(PERMISSION_VIEW_CONSULTATION, 'sort_cns_reviews')

    def sort_cns_reviews(self, by='Date'):
        """ Selects whitch method to use for sorting """

        if by == 'Date':
            return self.utSortObjsListByMethod(self.get_reviews(),
                                               'get_review_date', 1)
        else:
            return self.get_reviews_sorted(by)

    security.declareProtected(PERMISSION_VIEW_CONSULTATION,
                              'get_reviews_sorted')

    def get_reviews_sorted(self, rating=''):
        """ Returns the list of reviews sorted by rating value for the given rating """

        if rating not in self.getRatingTitles():
            return self.sort_reviews_page()
        reviews = [x for x in self.get_reviews()]
        reviews.sort(lambda x, y: cmp(int(y.getRatings()[rating]),
                                      int(x.getRatings()[rating])))
        return reviews

    security.declareProtected(PERMISSION_VIEW_CONSULTATION,
                              'sort_reviews_page')

    def sort_reviews_page(self, by='Date', REQUEST=None):
        """ Open the reviews page sorted acording to 'by' """
        if REQUEST is not None:
            return REQUEST.RESPONSE.redirect('%s/reviews_index_html?by=%s' %
                                             (self.absolute_url(), by))

    #site pages

    security.declareProtected(PERMISSION_REVIEW_CONSULTATION, 'edit_review')

    def edit_review(self):
        """ """
        auth_user = self.REQUEST.AUTHENTICATED_USER.getUserName()
        for review in self.objectValues(['Consultation Review']):
            if review.contributor == auth_user:
                return self.REQUEST.RESPONSE.redirect('%s/edit_html' %
                                                      review.absolute_url())
        self.setSessionErrors(['You cannot edit that Review.'])
        return self.REQUEST.RESPONSE.redirect(self.absolute_url() +
                                              '/index_html')

    security.declareProtected(PERMISSION_MANAGE_CONSULTATION,
                              'question_edit_html')
    question_edit_html = PageTemplateFile('zpt/question_edit', globals())

    security.declareProtected(PERMISSION_MANAGE_CONSULTATION,
                              'admin_ratelist_html')
    admin_ratelist_html = PageTemplateFile('zpt/admin_ratelist', globals())

    security.declareProtected(PERMISSION_MANAGE_CONSULTATION,
                              'admin_ratelists_html')
    admin_ratelists_html = PageTemplateFile('zpt/admin_ratelists', globals())

    security.declareProtected(PERMISSION_REVIEW_CONSULTATION,
                              'review_add_html')
    review_add_html = PageTemplateFile('zpt/review_add', globals())

    security.declareProtected(PERMISSION_MANAGE_CONSULTATION,
                              'manage_questions_html')
    manage_questions_html = PageTemplateFile('zpt/manage_questions', globals())

    security.declareProtected(PERMISSION_VIEW_CONSULTATION,
                              'reviews_index_html')
    reviews_index_html = PageTemplateFile('zpt/reviews_index', globals())

    security.declareProtected(view, 'index_html')
    index_html = PageTemplateFile('zpt/consultation_index', globals())

    security.declareProtected(PERMISSION_MANAGE_CONSULTATION, 'edit_html')
    edit_html = PageTemplateFile('zpt/consultation_edit', globals())

    security.declareProtected(PERMISSION_MANAGE_CONSULTATION,
                              'view_statistics_html')
    view_statistics_html = PageTemplateFile('zpt/view_statistics', globals())

    security.declareProtected(PERMISSION_MANAGE_CONSULTATION,
                              'instructions_html')
    instructions_html = PageTemplateFile('zpt/instructions', globals())
Exemplo n.º 5
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')
Exemplo n.º 6
0
class NySimpleConsultation(NyAttributes, Implicit, NyProperties, BTreeFolder2,
                           NyContainer, NyCheckControl, NyValidation, utils):
    """ """

    meta_type = METATYPE_OBJECT
    meta_label = LABEL_OBJECT

    all_meta_types = ()

    icon = 'misc_/NaayaContent/NySimpleConsultation.gif'
    icon_marked = 'misc_/NaayaContent/NySimpleConsultation_marked.gif'

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

    security = ClassSecurityInfo()

    edit_access = NyAccess(
        'edit_access', {
            PERMISSION_REVIEW_SIMPLECONSULTATION: "Submit comments",
            PERMISSION_MANAGE_SIMPLECONSULTATION: "Administer consultation",
        })

    def __init__(self, id, title, description, sortorder, start_date, end_date,
                 public_registration, allow_file, contributor, releasedate,
                 lang):
        """ """
        self.id = id
        NyValidation.__dict__['__init__'](self)
        NyCheckControl.__dict__['__init__'](self)
        NyContainer.__dict__['__init__'](self)
        BTreeFolder2.__init__(self)
        self.contributor = contributor
        try:
            del self.title
        except:
            pass
        self.save_properties(title, description, sortorder, start_date,
                             end_date, public_registration, allow_file,
                             releasedate, lang)
        NyProperties.__dict__['__init__'](self)
        self.submitted = 1

    security.declarePrivate('save_properties')

    def save_properties(self, title, description, sortorder, start_date,
                        end_date, public_registration, allow_file, 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

    security.declareProtected(PERMISSION_MANAGE_SIMPLECONSULTATION,
                              'saveProperties')

    def saveProperties(self,
                       title='',
                       description='',
                       sortorder='',
                       start_date='',
                       end_date='',
                       public_registration='',
                       allow_file='',
                       file='',
                       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.')

        if file and not file.read():
            self.setSession('title', title)
            self.setSession('description', description)
            self.setSessionErrors(['File must not be empty'])
            return REQUEST.RESPONSE.redirect('%s/edit_html?lang=%s' %
                                             (self.absolute_url(), lang))

        exfile = self.get_exfile()

        if file and exfile:
            exfile.saveUpload(file=file, lang=lang)
            downloadfilename = file.filename
            exfile._setLocalPropValue('downloadfilename', lang,
                                      downloadfilename)
        elif file and not exfile:
            addNyExFile(self, title=title, file=file, lang=lang, source='file')

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

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

    security.declareProtected(PERMISSION_MANAGE_SIMPLECONSULTATION,
                              'updateRequestRoleStatus')

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

    security.declareProtected(PERMISSION_MANAGE_SIMPLECONSULTATION,
                              '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 'Reviewer' not in roles:
            auth_tool.addRole('Reviewer',
                              [PERMISSION_REVIEW_SIMPLECONSULTATION])
        else:
            permission_add_role(self, PERMISSION_REVIEW_SIMPLECONSULTATION,
                                'Reviewer')

        #give permissions to administrators
        admin_permissions = self.permissionsOfRole('Administrator')
        site = self.getSite()
        if PERMISSION_MANAGE_SIMPLECONSULTATION not in admin_permissions:
            site.manage_permission(PERMISSION_MANAGE_SIMPLECONSULTATION,
                                   ('Administrator', ),
                                   acquire=1)
            site.manage_permission(PERMISSION_REVIEW_SIMPLECONSULTATION,
                                   ('Administrator', ),
                                   acquire=1)

    security.declareProtected(view, 'get_exfile')

    def get_exfile(self):
        """ Returns the first ExFile in the Simple Consultation, there should be only one. """

        try:
            exfile = self.objectValues(['Naaya Extended File'])[0]
        except IndexError:
            exfile = None

        return exfile

    security.declareProtected(view, 'check_exfile_for_lang')

    def check_exfile_for_lang(self, lang):
        """ Checks if there is a file uploaded for the given language. """

        return self.get_exfile().getFileItem(lang).size > 0

    security.declareProtected(view, 'get_exfile_langs')

    def get_exfile_langs(self):
        """ Returns the languages for witch NyExFile contains files. """

        return [
            language for language in self.getSite().gl_get_languages_map()
            if self.check_exfile_for_lang(language['id'])
        ]

    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

    security.declareProtected(view, 'check_contributor_comment')

    def check_contributor_comment(self, contributor='', REQUEST=None):
        """ Returns True if user already posted a comment """

        if not contributor and REQUEST:
            contributor = REQUEST.AUTHENTICATED_USER.getUserName()

        return contributor in [
            comment.contributor
            for comment in self.objectValues(['Simple Consultation Comment'])
        ]

    security.declareProtected(PERMISSION_REVIEW_SIMPLECONSULTATION,
                              'addComment')

    def addComment(self,
                   title='',
                   contributor_name='',
                   message='',
                   file='',
                   REQUEST=None):
        """ """

        if not title or not contributor_name or not message:
            self.setSession('title', title)
            self.setSession('contributor_name', contributor_name)
            self.setSession('message', message)
            self.setSessionErrors(['Fill in all mandatory fields.'])
            return REQUEST.RESPONSE.redirect(self.absolute_url() +
                                             '/add_simpleconsultation_comment')

        contributor = REQUEST.AUTHENTICATED_USER.getUserName()
        if not self.allow_file: file = ''
        days = self.get_days_left()

        if days[0] == 1 and days[1] > 0:
            if not self.check_contributor_comment(contributor):
                addSimpleConsultationComment(self, title, contributor,
                                             contributor_name, message, file,
                                             REQUEST)
            else:
                return REQUEST.RESPONSE.redirect(
                    self.absolute_url() +
                    '/add_simpleconsultation_comment?status=failed')
        elif days[0] == 1 and days[1] <= 0:
            return REQUEST.RESPONSE.redirect(
                self.absolute_url() +
                '/add_simpleconsultation_comment?status=late')
        elif days[0] <= 0:
            return REQUEST.RESPONSE.redirect(
                self.absolute_url() +
                '/add_simpleconsultation_comment?status=soon')

    def checkSimpleConsultationUser(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.checkPermissionReviewSimpleConsultation()

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

    #permissions
    def checkPermissionReviewSimpleConsultation(self):
        """
        Check for reviewing the Simple Consultation.
        """
        return self.checkPermission(PERMISSION_REVIEW_SIMPLECONSULTATION)

    def checkPermissionManageSimpleConsultation(self):
        """
        Check for managing the Simple Consultation.
        """
        return self.checkPermission(PERMISSION_MANAGE_SIMPLECONSULTATION)

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

    #site pages
    security.declareProtected(view, 'index_html')
    index_html = PageTemplateFile('zpt/simpleconsultation_index', globals())

    security.declareProtected(PERMISSION_MANAGE_SIMPLECONSULTATION,
                              'edit_html')
    edit_html = PageTemplateFile('zpt/simpleconsultation_edit', globals())

    security.declareProtected(PERMISSION_REVIEW_SIMPLECONSULTATION,
                              'add_simpleconsultation_comment')
    add_simpleconsultation_comment = PageTemplateFile(
        'zpt/simpleconsultation_comment_add', globals())
Exemplo n.º 7
0
class NyForum(NyRoleManager, NyPermissions, NyForumBase, Folder, utils,
              LocalPropertyManager):
    """ """
    interface.implements(INyForum)

    meta_type = METATYPE_NYFORUM
    meta_label = LABEL_NYFORUM
    icon = 'misc_/NaayaForum/NyForum.gif'
    icon_marked = 'misc_/NaayaForum/NyForum_marked.gif'
    topics_listing = 'Plain table'
    topics_ordering = 'Reverse: Chronological order'
    message_top = LocalProperty('message_top')
    message_outdated = LocalProperty('message_outdated')

    manage_options = (Folder.manage_options[0:2] +
                      ({
                          'label': 'Properties',
                          'action': 'manage_edit_html'
                      }, ) + Folder.manage_options[3:8])

    meta_types = ({
        'name': METATYPE_NYFORUMTOPIC,
        'action': 'manage_addNyForumTopic_html'
    }, )
    all_meta_types = meta_types

    security = ClassSecurityInfo()

    edit_access = NyAccess(
        'edit_access', {
            view: "Access content",
            PERMISSION_MODIFY_FORUMTOPIC: "Modify topic",
            PERMISSION_ADD_FORUMMESSAGE: "Add message",
            PERMISSION_MODIFY_FORUMMESSAGE: "Modify message",
        })

    #constructors
    security.declareProtected(view_management_screens,
                              'manage_addNyForumTopic_html')
    manage_addNyForumTopic_html = manage_addNyForumTopic_html

    security.declareProtected(PERMISSION_MODIFY_FORUMTOPIC, 'topic_add_html')
    topic_add_html = topic_add_html

    security.declareProtected(PERMISSION_MODIFY_FORUMTOPIC, 'addNyForumTopic')
    addNyForumTopic = addNyForumTopic

    def __init__(self, id, title, description, categories, file_max_size,
                 contributor):
        """ """
        self.id = id
        self.title = title
        self.description = description
        self.categories = categories
        self.file_max_size = file_max_size
        self.contributor = contributor
        NyForumBase.__dict__['__init__'](self)
        #make this object available for portal search engine
        self.submitted = 1
        self.approved = 1

    def loadDefaultData(self):
        """
        Sets default permissions
        """
        self.manage_permission(PERMISSION_ADD_FORUMMESSAGE, ['Anonymous'],
                               acquire=1)
        self.manage_permission(PERMISSION_MODIFY_FORUMTOPIC,
                               ['Administrator', 'Manager'],
                               acquire=1)
        self.manage_permission(PERMISSION_SKIP_CAPTCHA,
                               ['Administrator', 'Manager'],
                               acquire=1)

    def __setstate__(self, state):
        """
        For backwards compatibility.
        """
        NyForum.inheritedAttribute("__setstate__")(self, state)
        if not hasattr(self, 'file_max_size'):
            self.file_max_size = 0

    security.declarePrivate('_get_template')

    def _get_template(self, name):
        template = self._getOb('emailpt_%s' % name, None)
        if template is not None:
            return template.render_email

        template = email_templates.get(name, None)
        if template is not None:
            return template.render_email

        raise ValueError('template for %r not found' % name)

    #api
    def get_forum_object(self):
        return self

    def get_forum_path(self, p=0):
        return self.absolute_url(p)

    def get_forum_categories(self):
        return self.categories

    def get_topics(self):
        return self.objectValues(METATYPE_NYFORUMTOPIC)

    def count_topics(self):
        return len(self.objectIds(METATYPE_NYFORUMTOPIC))

    def getObjectsForValidation(self):
        return []

    def count_notok_objects(self):
        return 0

    def count_notchecked_objects(self):
        return 0

    security.declarePrivate('processIdentity')

    def processIdentity(self):
        """
        Returns information about the user who created the topic/message
        and the posting date.
        """
        return self.REQUEST.AUTHENTICATED_USER.getUserName(
        ), self.utGetTodayDate()

    security.declarePrivate('handleAttachmentUpload')

    def handleAttachmentUpload(self, ob, file):
        """
        Handle upload of a file. A B{File} object will be created inside
        the B{given} object.
        """
        if file != '':
            if hasattr(file, 'filename'):
                if file.filename != '':
                    if file.filename.find('\\') != -1:
                        id = file.filename.split('\\')[-1]
                    else:
                        id = file.filename
                    #check file size
                    id = self.utSlugify(id)
                    if len(file.read()
                           ) <= self.file_max_size or self.file_max_size == 0:
                        ob.manage_addFile(id=id, file=file)

    def can_be_seen(self):
        """
        Indicates if the current user has access to the current forum.
        """
        return self.checkPermission(view)

    def has_restrictions(self):
        """
        Indicates if this folder has restrictions for the current user.
        """
        return not self.acquiredRolesAreUsedBy(view)

    def get_roles_with_access(self):
        """
        Returns a list of roles that have access to this forum.
        """
        r = []
        ra = r.append
        for x in self.rolesOfPermission(view):
            if x['selected'] and x['name'] not in [
                    'Administrator', 'Anonymous', 'Manager', 'Owner'
            ]:
                ra(x['name'])
        return r

    security.declarePublic('getPublishedFolders')

    def getPublishedFolders(self):
        if not self.checkPermissionView():
            return []
        return self.objectValues(METATYPE_NYFORUMTOPIC)

    def getPublishedObjects(self):
        return []

    def getObjects(self):
        return self.getPublishedFolders()

    def getPendingFolders(self):
        return []

    def getFolders(self):
        return self.getPublishedFolders()

    def hasContent(self):
        return (len(self.getObjects()) > 0)

    def get_sort_options(self):
        """ return a maping of sorting options"""
        return [['Subject', 'subject', False],
                ['Access type', 'access', False], ['Status', 'status', False],
                ['Author', 'author', False],
                ['Number of replies', 'count_messages', False],
                ['Number of views', 'views', False],
                ['Chronological order', 'last_message', False],
                ['Reverse: Subject', 'subject', True],
                ['Reverse: Access type', 'access', True],
                ['Reverse: Status', 'status', True],
                ['Reverse: Author', 'author', True],
                ['Reverse: Number of replies', 'count_messages', True],
                ['Reverse: Number of views', 'views', True],
                ['Reverse: Chronological order', 'last_message', True]]

    security.declareProtected(view, 'checkTopicsPermissions')

    def checkTopicsPermissions(self):
        """
        This function is called on the forum index and it checkes whether or not
        to display the various buttons on that form.
        Returns in a list of tuples: which buttons should be visible,
        a list of topics, sorted reversed by the date of the last post.
        """
        REQUEST = self.REQUEST
        skey = REQUEST.get('skey', None)
        rkey = None
        if skey is None:
            for option in self.get_sort_options():
                if self.topics_ordering == option[0]:
                    skey = option[1]
                    rkey = option[2]
        if rkey is None:
            rkey = REQUEST.get('rkey')
            if not rkey:
                rkey = False
            else:
                rkey = rkey not in ['0', 'False']
        if self.topics_listing == 'Plain table':
            topics = {'Plain table': []}
        else:
            topics = {}
            for category in self.categories:
                topics[category] = []
        btn_select, btn_delete, can_operate = 0, 0, 0
        # btn_select - if there is at least one permisson to delete or copy an object
        # btn_delete - if there is at least one permisson to delete an object
        for x in self.objectValues(METATYPE_NYFORUMTOPIC):
            del_permission = x.checkPermissionModifyForumTopic()
            edit_permission = x.checkPermissionModifyForumTopic()
            if del_permission: btn_select = 1
            if del_permission: btn_delete = 1
            if edit_permission: can_operate = 1
            if self.topics_listing == 'Plain table':
                topics['Plain table'].append(
                    (del_permission, edit_permission, x))
            else:
                if x.category in topics.keys():
                    topics[x.category].append(
                        (del_permission, edit_permission, x))
                elif 'Other' in topics.keys():
                    topics['Other'].append(
                        (del_permission, edit_permission, x))
                else:
                    topics['Other'] = [(del_permission, edit_permission, x)]
        can_operate = can_operate or btn_select
        for topics_category in topics.values():
            if skey == 'subject':
                topics_category.sort(key=lambda x: x[2].title_or_id().lower(),
                                     reverse=rkey)
            elif skey == 'access':
                topics_category.sort(key=lambda x: x[2].access_type(),
                                     reverse=rkey)
            elif skey == 'status':
                topics_category.sort(key=lambda x: x[2].is_topic_opened(),
                                     reverse=rkey)
            elif skey == 'views':
                topics_category.sort(
                    key=lambda x: self.getTopicHits(topic=x[2].id),
                    reverse=rkey)
            elif skey == 'last_message':
                topics_category.sort(
                    key=lambda x: x[2].get_last_message().postdate,
                    reverse=rkey)
            else:
                try:
                    topics_category.sort(key=lambda x: getattr(x[2], skey),
                                         reverse=rkey)
                except AttributeError:
                    #This means the sort key was wrong (manually altered)
                    pass
        return btn_select, btn_delete, can_operate, topics, skey, rkey

    def checkPermissionSkipCaptcha(self):
        return getSecurityManager().checkPermission('Naaya - Skip Captcha',
                                                    self)

    #zmi actions
    security.declareProtected(view_management_screens, 'manageProperties')

    def manageProperties(self,
                         title='',
                         description='',
                         categories='',
                         file_max_size='',
                         topics_listing='',
                         topics_ordering='',
                         REQUEST=None):
        """ """
        contributor = self.REQUEST.AUTHENTICATED_USER.getUserName()
        self.contributor = contributor
        self.title = title
        self.description = description
        self.categories = self.utConvertLinesToList(categories)
        self.file_max_size = abs(int(file_max_size))
        self.topics_listing = topics_listing
        self.topics_ordering = topics_ordering
        self._p_changed = 1
        if REQUEST: REQUEST.RESPONSE.redirect('manage_edit_html?save=ok')

    #zmi actions
    security.declareProtected(PERMISSION_ADD_FORUM, 'saveProperties')

    def saveProperties(self,
                       title='',
                       description='',
                       categories='',
                       file_max_size='',
                       topics_listing='',
                       topics_ordering='',
                       message_top='',
                       message_outdated='',
                       alphabetic_categories=None,
                       REQUEST=None):
        """ """
        contributor = self.REQUEST.AUTHENTICATED_USER.getUserName()
        self.contributor = contributor
        self.title = title
        self.description = description
        self.categories = self.utConvertLinesToList(categories)
        self.file_max_size = abs(int(file_max_size))
        self.topics_listing = topics_listing
        self.topics_ordering = topics_ordering
        lang = self.gl_get_selected_language()
        self._setLocalPropValue('message_top', lang, message_top)
        self._setLocalPropValue('message_outdated', lang, message_outdated)
        self.alphabetic_categories = alphabetic_categories
        self._p_changed = 1
        if REQUEST:
            self.setSessionInfoTrans(MESSAGE_SAVEDCHANGES,
                                     date=self.utGetTodayDate())
            REQUEST.RESPONSE.redirect('edit_html?save=ok')

    #site actions
    security.declareProtected(PERMISSION_MODIFY_FORUMTOPIC, 'deleteTopics')

    def deleteTopics(self, ids='', REQUEST=None):
        """ """
        try:
            self.manage_delObjects(self.utConvertToList(ids))
        except:
            self.setSessionErrorsTrans('Error while deleting data.')
        else:
            self.setSessionInfoTrans('Topic(s) deleted.')
        if REQUEST:
            REQUEST.RESPONSE.redirect('%s/index_html' % self.absolute_url())

    #
    # Statistics
    #
    security.declarePrivate("_getStatisticsContainerCursor")

    def _getStatisticsContainerCursor(self):
        """ Create statistics container if it doesn't exists and return it
        """
        stats_container = getattr(self, STATISTICS_CONTAINER, None)
        if stats_container is None:
            # do DB was ever created
            cursor = None
        else:
            try:
                cursor = stats_container.cursor()
            except naaya.sql.DbMissing:
                # DB was removed
                cursor = None

        if cursor is None:
            stats_container = naaya.sql.new_db()
            setattr(self, STATISTICS_CONTAINER, stats_container)
            table = ("CREATE TABLE HITS"
                     "(id INTEGER PRIMARY KEY ASC AUTOINCREMENT")
            for (col, val) in STATISTICS_COLUMNS.items():
                table += ", " + col + " " + val
            table += ")"
            cursor = stats_container.cursor()
            cursor.execute(table)

        return cursor

    def _removeStatisticsContainer(self):
        """ Remove statistics container if exists
        """
        stats_container = getattr(self, STATISTICS_CONTAINER, None)
        if stats_container is not None:
            if hasattr(stats_container, 'drop'):
                stats_container.drop()
            delattr(self, STATISTICS_CONTAINER)

    security.declareProtected(view, 'getTopicHits')

    def getTopicHits(self, topic):
        """ Returns statistics for given topic
        """
        cursor = self._getStatisticsContainerCursor()
        cursor.execute("SELECT hits from HITS where topic=?", (topic, ))
        res = cursor.fetchone()
        if not res:
            cursor.execute("INSERT into HITS(topic) values(?)", (topic, ))
            return 0
        else:
            return res[0]

    security.declarePrivate('setTopicHits')

    def setTopicHits(self, topic, how_many=1):
        hits = self.getTopicHits(topic) + how_many
        cursor = self._getStatisticsContainerCursor()
        cursor.execute("UPDATE HITS set hits=? where topic=?", (hits, topic))

    security.declareProtected(view, 'updateTopicHits')

    def updateTopicHits(self, topic):
        """ Update hits for topic
        """
        self.setTopicHits(topic, 1)

    security.declareProtected(view, 'removeTopicHits')

    def removeTopicHits(self, topic):
        """ Remove hits record for topic
        """
        cursor = self._getStatisticsContainerCursor()
        cursor.execute("DELETE FROM HITS where topic=?", (topic, ))

    security.declareProtected(view, 'hasVersion')

    def hasVersion(self):
        """ """
        return False

    security.declarePublic('export_this')

    def export_this(self, folderish=0):
        """ """
        return ''

    security.declareProtected(view, 'get_categories')

    def get_categories(self):
        """ return categories, sorted if the option is set on the forum
        """
        if getattr(self, 'alphabetic_categories', None):
            return sorted(self.categories)
        return self.categories

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

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

    security.declareProtected(view, 'messages_feed')
    messages_feed = messages_feed

    security.declareProtected(PERMISSION_ADD_FORUM, 'edit_html')
    edit_html = PageTemplateFile('zpt/forum_edit', globals())

    security.declareProtected(PERMISSION_ADD_FORUM, 'forum_add_html')
    forum_add_html = PageTemplateFile('zpt/forum_add', globals())