Beispiel #1
0
    def __call__(self):
        self.protect()
        self.errors = []

        parts = str(self.request.form['folder'].lstrip('/')).split('/')
        parent = self.site.unrestrictedTraverse('/'.join(parts[:-1]))
        self.dest = parent.restrictedTraverse(parts[-1])

        try:
            self.dest.manage_pasteObjects(self.request['__cp'])
        except ConflictError:
            raise
        except Unauthorized:
            # avoid this unfriendly exception text:
            # "You are not allowed to access 'manage_pasteObjects' in this
            # context"
            self.errors.append(
                _(u'You are not authorized to paste ${title} here.',
                    mapping={u'title': self.objectTitle(self.dest)}))
        except ValueError as e:
            if 'Disallowed subobject type: ' in e.args[0]:
                msg_parts = e.args[0].split(':')
                self.errors.append(
                    _(u'Disallowed subobject type "${type}"',
                        mapping={u'type': msg_parts[1].strip()}))
            else:
                raise e

        return self.message()
 def __call__(self):
     context = aq_inner(self.context)
     request = aq_inner(self.request)
     walker = self.walker()
     options = dict(target_type=walker.src_portal_type)
     clicked = request.form.has_key
     portal_url = getToolByName(context, 'portal_url')()
     if not haveContentMigrations:
         msg = _(u'Please install contentmigrations to be able to migrate to blobs.')
         IStatusMessage(request).addStatusMessage(msg, type='warning')
         options['nomigrations'] = 42
     elif clicked('migrate'):
         output = self.migration()
         # Only count actual migration lines
         lines = output.split('\n')
         count = len([l for l in lines if l.startswith('Migrating')])
         msg = _(u'blob_migration_info',
             default=u'Blob migration performed for ${count} item(s).',
             mapping={'count': count})
         IStatusMessage(request).addStatusMessage(msg, type='info')
         options['count'] = count
         options['output'] = output
     elif clicked('cancel'):
         msg = _(u'Blob migration cancelled.')
         IStatusMessage(request).addStatusMessage(msg, type='info')
         request.RESPONSE.redirect(portal_url)
     else:
         options['available'] = len(list(walker.walk()))
     return self.index(**options)
    def action_reset_passwd(self, action):
        data, errors = self.extractData()

        # extra password validation
        self.validate_password(action, data)

        if action.form.widgets.errors:
            self.status = self.formErrorsMessage
            return

        membertool = getToolByName(self.context, 'portal_membership')

        password = data['new_password']
        if isinstance(password, unicode):
            password = password.encode('utf8')

        try:
            membertool.setPassword(password, None, REQUEST=self.request)
        except AttributeError:
            failMessage = _(u'While changing your password an AttributeError '
                            u'occurred. This is usually caused by your user '
                            u'being defined outside the portal.')

            IStatusMessage(self.request).addStatusMessage(
                _(failMessage), type="error"
            )
            return

        IStatusMessage(self.request).addStatusMessage(
            _("Password changed"), type="info"
        )
    def validate(self, action, data):
        errors = super(UserDataPanel, self).validate(action, data)

        if not self.widgets['email'].error():
            reg_tool = getToolByName(self.context, 'portal_registration')
            props = getToolByName(self.context, 'portal_properties').site_properties
            if props.getProperty('use_email_as_login'):
                err_str = ''
                try:
                    id_allowed = reg_tool.isMemberIdAllowed(data['email'])
                except Unauthorized:
                    err_str = _('message_email_cannot_change',
                                u"Sorry, you are not allowed to change your email address.")
                else:

                    if not id_allowed:
                        # Keeping your email the same (which happens when you
                        # change something else on the personalize form) or
                        # changing it back to your login name, is fine.
                        membership = getToolByName(self.context, 'portal_membership')
                        if self.userid:
                            member = membership.getMemberById(self.userid)
                        else:
                            member = membership.getAuthenticatedMember()
                        if data['email'] not in (member.getId(), member.getUserName()):
                            err_str = _('message_email_in_use',
                                        u"The email address you selected is already in use "
                                         "or is not valid as login name. Please choose "
                                         "another.")

                if err_str:
                    errors.append(WidgetInputError('email', u'label_email', err_str))
                    self.widgets['email'].error = err_str

        return errors
Beispiel #5
0
    def current_workflow(self):
        context = aq_inner(self.context)
        portal_workflow = getToolByName(context, 'portal_workflow')
        default_workflow = self.default_workflow(False)
        nondefault = [info[0] for info in portal_workflow.listChainOverrides()]
        chain = portal_workflow.getChainForPortalType(self.type_id)
        empty_workflow_dict = dict(id='[none]',
                                   title=_(u"label_no_workflow"),
                                   description= [_(u"description_no_workflow",
                                   default=u"This type has no workflow. The visibilty "
                                       u"of items of this type is determined by "
                                       u"the folder they are in.")])

        if self.type_id in nondefault:
            if chain:
                wf_id = chain[0]
                wf = getattr(portal_workflow, wf_id)
                title = translate(wf.title, domain='plone', context=self.request)
                return dict(id=wf.id, title=title, description=format_description(wf.description, self.request))
            else:
                return empty_workflow_dict

        if default_workflow == '[none]':
            return empty_workflow_dict

        default_title = translate(default_workflow.title, domain='plone',
                                  context=self.request)
        return dict(id='(Default)',
                    title=_(u"label_default_workflow_title",
                        default=u"Default workflow (${title})",
                        mapping=dict(title=default_title)),
                    description=format_description(default_workflow.description, self.request))
Beispiel #6
0
def validate_coursebuilder(form, action, data):
    """ Validate the course builder form. """

    division = form.request.form['form.division']
    newdivision = form.request.form['form.newdivision']
    if not division and not newdivision:
        dw = form.widgets.get('division')
        dw._error = WidgetInputError(form.context.__name__, dw.label, _('Missing division.'))
        return dw._error

    if newdivision:
        brains = form.context.portal_catalog.searchResults(Type='Division')
        if brains:
            if newdivision in [x.Title for x in brains]:
                dw = form.widgets.get('division')
                dw._error = WidgetInputError(form.context.__name__, 
                                             dw.label, 
                                             _('Division with the same title already exists.'))
                return dw._error

    coursename = form.request.form['form.coursename']
    if not coursename:
        cnw = form.widgets.get('coursename')
        cnw._error = WidgetInputError(form.context.__name__, cnw.label, _('Missing course name.'))
        return cnw._error
Beispiel #7
0
 def update(self):
     base_url = self.context.absolute_url()
     base_vocabulary = '%s/@@getStorageVocabulary' % base_url
     push_state_url = '%s/storage_contents{path}' % base_url
     options = {
         'vocabularyUrl': base_vocabulary,
         'pushStateUrl': push_state_url,
         'traverseView': True,
         # TODO verify that get_url result in a valid location dir.
         'traverseSubpath': self.get_current_path(),
         'indexOptionsUrl': '%s/@@qsOptions' % base_url,
         'contextInfoUrl': '%s/@@sc-contextInfo' % base_url,
         'attributes': attributes,
         'activeColumns': ['ModificationDate', 'getObjSize'],
         'activeColumnsCookie': 'activeStorageColumns',
         'availableColumns': {
             'id': translate(_('ID'), context=self.request),
             'ModificationDate': translate(_('Last modified'), context=self.request),  # noqa
             'getObjSize': translate(_('Object Size'), context=self.request),  # noqa
         },
         'upload': False,
         'rearrange': False,
         'buttons': self.get_actions(),
         'menuGenerator': 'repodonostorage-url/js/actionmenu',
         'tableRowItemAction': {
             # switch off the default navigation js method
             'other': None,
         },
         'collectionConstructor': 'repodonostorage-url/js/collection',
     }
     self.options = json.dumps(options)
Beispiel #8
0
    def handle_rename(self, action):
        data, errors = self.extractData()
        if errors:
            return

        parent = aq_parent(aq_inner(self.context))
        sm = getSecurityManager()
        if not sm.checkPermission('Copy or Move', parent):
            raise Unauthorized(_(u'Permission denied to rename ${title}.',
                                 mapping={u'title': self.context.title}))

        oldid = self.context.getId()
        newid = data['new_id']
        newid = INameChooser(parent).chooseName(newid, self.context)

        context_state = getMultiAdapter(
            (self.context, self.request), name='plone_context_state')
        if context_state.is_default_page():
            parent.setDefaultPage(newid)
        # Requires cmf.ModifyPortalContent permission
        self.context.title = data['new_title']
        # Requires zope2.CopyOrMove permission
        parent.manage_renameObjects([oldid, ], [str(newid), ])

        transaction.savepoint(optimistic=True)
        notify(ObjectModifiedEvent(self.context))

        IStatusMessage(self.request).add(
            _(u"Renamed '${oldid}' to '${newid}'.", mapping={
                u'oldid': oldid, u'newid': newid}))

        self.request.response.redirect(self.context.absolute_url())
Beispiel #9
0
 def morphVersionDataToHistoryFormat(vdata, version_id):
     meta = vdata["metadata"]["sys_metadata"]
     userid = meta["principal"]
     preview_url = \
         "%s/versions_history_form?version_id=%s#version_preview" % (
             context_url,
             version_id
         )
     info = dict(
         type='versioning',
         action=_(u"Edited"),
         transition_title=_(u"Edited"),
         actorid=userid,
         time=meta["timestamp"],
         comments=meta['comment'],
         version_id=version_id,
         preview_url=preview_url,
         revert_url="%s/revertversion" % context_url,
     )
     if can_diff:
         if version_id > 0:
             info["diff_previous_url"] = (
                 "%s/@@history?one=%s&two=%s" %
                 (context_url, version_id, version_id-1)
             )
         if not rt.isUpToDate(context, version_id):
             info["diff_current_url"] = (
                 "%s/@@history?one=current&two=%s" %
                 (context_url, version_id)
             )
     info.update(self.getUserInfo(userid))
     return info
Beispiel #10
0
    def __call__(self):
        self.errors = []
        self.protect()
        id = self.request.form.get('id')
        ordering = self.getOrdering()

        if ordering is None:
            self.errors.append(_('This folder does not support ordering'))
            return self.message()

        delta = self.request.form['delta']

        if delta == 'top':
            ordering.moveObjectsToTop([id])
            return self.message()

        if delta == 'bottom':
            ordering.moveObjectsToBottom([id])
            return self.message()

        delta = int(delta)
        subset_ids = json_loads(self.request.form.get('subset_ids', '[]'))
        if subset_ids:
            position_id = [
                (ordering.getObjectPosition(i), i) for i in subset_ids
            ]
            position_id.sort()
            if subset_ids != [i for position, i in position_id]:
                self.errors.append(_('Client/server ordering mismatch'))
                return self.message()

        ordering.moveObjectsByDelta([id], delta)
        return self.message()
Beispiel #11
0
    def do_action(self):
        if not self.context.cb_dataValid():
            return self.do_redirect(
                self.canonical_object_url,
                _(u'Copy or cut one or more items to paste.'),
                'error'
            )
        try:
            self.context.manage_pasteObjects(self.request['__cp'])
        except ConflictError:
            raise
        except Unauthorized as e:
            self.do_redirect(
                self.canonical_object_url,
                _(u'You are not authorized to paste here.'),
                e
            )
        except CopyError as e:
            error_string = str(e)
            if 'Item Not Found' in error_string:
                return self.do_redirect(
                    self.canonical_object_url,
                    _(u'The item you are trying to paste could not be found. '
                      u'It may have been moved or deleted after you copied or '
                      u'cut it.'),
                    'error',
                )
        except Exception as e:
            if '__cp' in self.request:
                self.do_redirect(self.canonical_object_url, e, 'error', e)

        return self.do_redirect(self.canonical_object_url,
                                _(u'Item(s) pasted.'))
Beispiel #12
0
    def manageGroup(self, groups=[], delete=[]):
        CheckAuthenticator(self.request)
        context = aq_inner(self.context)

        groupstool = context.portal_groups
        utils = getToolByName(context, 'plone_utils')
        groupstool = getToolByName(context, 'portal_groups')

        message = _(u'No changes made.')

        for group in groups:
            roles = [r for r in self.request.form['group_' + group] if r]
            group_obj = groupstool.getGroupById(group)
            current_roles = group_obj.getRoles()
            if not self.is_zope_manager:
                # don't allow adding or removing the Manager role
                if ('Manager' in roles) != ('Manager' in current_roles):
                    raise Forbidden

            groupstool.editGroup(group, roles=roles, groups=())
            message = _(u'Changes saved.')

        if delete:
            for group_id in delete:
                group = groupstool.getGroupById(group_id)
                if 'Manager' in group.getRoles() and not self.is_zope_manager:
                    raise Forbidden

            groupstool.removeGroups(delete)
            message = _(u'Group(s) deleted.')

        utils.addPortalMessage(message)
    def handle_restart_action(self, action):
        CheckAuthenticator(self.request)
        if not self.available():
            self.status = _(
                u'text_not_allowed_manage_server',
                default=u'You are not allowed to manage the Zope server.'
            )
            return

        try:
            user = '******' % getSecurityManager().getUser().getUserName()
        except:
            user = '******'
        logger.info("Restart requested by %s" % user)
        shutdown(1)
        url = self.request.get('URL')
        # TODO: returning html has no effect in button handlers
        self.request.response.setHeader('X-Theme-Disabled', 'True')
        return """<html><head>
            <meta http-equiv="refresh" content="5; url={0}">
        </head><body>{1}</body></html>""".format(
            escape(url, 1),
            _('plone_restarting',
                default=u"Zope is restarting. This page will refresh in 30"
                        u" seconds...")
        )
    def getErrors(self):
        if self.request.method != 'POST':
            return
        password = self.request.form.get('password')
        password2 = self.request.form.get('password2')
        userid = self.request.form.get('userid')
        reg_tool = getToolByName(self.context, 'portal_registration')
        pw_fail = reg_tool.testPasswordValidity(password, password2)
        state = {}
        if pw_fail:
            state['password'] = pw_fail

        # Determine if we're checking userids or not
        pw_tool = getToolByName(self.context, 'portal_password_reset')
        if not pw_tool.checkUser():
            return state

        if not userid:
            state['userid'] = _(
                'This field is required, please provide some information.',
            )
        if state:
            state['status'] = 'failure'
            state['portal_status_message'] = _(
                'Please correct the indicated errors.',
            )
        return state
 def __call__(self):
     method = self.request.get('REQUEST_METHOD', 'GET')
     if (method != 'POST') or not int(self.request.form.get('form.submitted', 0)):
         return self.index()
     
     if self.request.form.get('form.button.Cancel') == 'Cancel':
         #User canceled deletion...
         message = _(u'The deletion of ${title} has been canceled.',
                     mapping={u'title' : self.context.Title()})
         self.context.plone_utils.addPortalMessage(message)
         self.request.response.redirect(self.context.absolute_url())
         return
     
     parent = self.context.aq_inner.aq_parent
     
     self.processChilds()
     
     parent.manage_delObjects(self.context.getId())
     
     title = self.context.Title()
     message = _(u'${title} has been deleted.',
                 mapping={u'title': self.context.Title()})
     transaction_note('Deleted %s' % self.context.absolute_url())
     self.context.plone_utils.addPortalMessage(message)
     
     self.request.response.redirect(parent.absolute_url())
    def validate(self):
        """Validate sendto_form"""

        errors = {"send_to_address": "", "send_from_address": ""}
        gotErrors = False

        if not self.request.get("form.submitted"):
            return errors, gotErrors

        plone_utils = self.context.plone_utils
        send_to_address = self.request.get("send_to_address")
        send_from_address = self.request.get("send_from_address")

        if not send_to_address:
            errors["send_to_address"] = _(u"Please submit an email address.")
            gotErrors = True
        elif not plone_utils.validateEmailAddresses(send_to_address):
            errors["send_to_address"] = _(u"Please submit a valid email address.")
            gotErrors = True

        if not send_from_address:
            errors["send_from_address"] = _(u"Please submit an email address.")
            gotErrors = True
        elif not plone_utils.validateSingleEmailAddress(send_from_address):
            errors["send_from_address"] = _(u"Please submit a valid email address.")
            gotErrors = True

        return errors, gotErrors
Beispiel #17
0
    def handle_edit_action(self, action, data):
        # If the CC license option has been chosen, copy the new fields
        # into the license
        if 'Creative Commons License' == data['default_license']:
            ad = self.adapters[IContentLicensingSettingsForm]
            # Get the hidden field data from the view in the form
            ad.setCCLicense(self.request['license_cc_name'],
                            self.request['license_cc_url'],
                            self.request['license_cc_button'])

        # Apply form changes        
        if form.applyChanges(self.context, self.form_fields, data, self.adapters):

            # If there is a new license in the form, add it to the properties page
            if data.has_key('new_license_name') and data['new_license_name']:
                ad = self.adapters[IContentLicensingNewLicenseForm]
                ad.setNewLicense(data['new_license_name'], 
                                 data['new_license_url'], 
                                 data['new_license_icon'])

            self.status = _("Changes saved.")
            self._on_save(data)
            self.request['fieldset.current'] = u'fieldsetlegend-contentlicensingsettings'
        else:
            self.status = _("No changes made.")
Beispiel #18
0
 def current_workflow(self):
     context = aq_inner(self.context)
     portal_workflow = getToolByName(context, 'portal_workflow')
     try:
         nondefault = [info[0] for info in portal_workflow.listChainOverrides()]
         if self.type_id in nondefault:
             wf_id = portal_workflow.getChainForPortalType(self.type_id)[0]
         else:
             default_workflow = self.default_workflow(False)
             default_title = translate(default_workflow.title,
                                       domain='plone',
                                       context=self.request)
             return dict(id='(Default)',
                     title=_(u"label_default_workflow_title",
                             default=u"Default workflow (${title})",
                             mapping=dict(title=default_title)),
                     description=format_description(default_workflow.description, self.request))
     except IndexError:
         return dict(id='[none]',
                 title=_(u"label_no_workflow",
                     default=u"No workflow"),
                 description=[
                     _(u"description_no_workflow",
                     default=u"This type has no workflow. The visibilty of "
                             u"items of this type is determined by the "
                             u"folder they are in.")])
     wf = getattr(portal_workflow, wf_id)
     title = translate(wf.title,
                       domain='plone',
                       context=self.request)
     return dict(id=wf.id, title=title, description=format_description(wf.description, self.request))
Beispiel #19
0
    def prepareObjectTabs(self,
                          default_tab='view',
                          sort_first=['folderContents']):
        context = self.context
        mt = getToolByName(context, 'portal_membership')
        tabs = []
        navigation_root_url = context.absolute_url()

        if mt.checkPermission(SetOwnProperties, context):
            tabs.append({
                'title': _('title_personal_information_form',
                           u'Personal Information'),
                'url': navigation_root_url + '/@@personal-information',
                'selected': (self.__name__ == 'personal-information'),
                'id': 'user_data-personal-information',
            })
            tabs.append({
                'title': _(u'Personal Preferences'),
                'url': navigation_root_url + '/@@personal-preferences',
                'selected': (self.__name__ == 'personal-preferences'),
                'id': 'user_data-personal-preferences',
            })

        member = mt.getAuthenticatedMember()
        if member.canPasswordSet():
            tabs.append({
                'title': _('label_password', u'Password'),
                'url': navigation_root_url + '/@@change-password',
                'selected': (self.__name__ == 'change-password'),
                'id': 'user_data-change-password',
            })
        return tabs
def get_member_by_login_name(context, login_name, raise_exceptions=True):
    """Get a member by his login name.

    If a member with this login_name as userid exists, we happily
    return that member.

    If raise_exceptions is False, we silently return None.
    """
    membership = getToolByName(context, 'portal_membership')
    # First the easy case: it may be a userid after all.
    member = membership.getMemberById(login_name)

    if member is not None:
        return member

    # Try to find this user via the login name.
    acl = getToolByName(context, 'acl_users')
    userids = [user.get('userid') for user in
               acl.searchUsers(name=login_name, exact_match=True)
               if user.get('userid')]
    if len(userids) == 1:
        userid = userids[0]
        member = membership.getMemberById(userid)
    elif len(userids) > 1:
        if raise_exceptions:
            raise ValueError(
                _(u'Multiple users found with the same login name.'))
    if member is None and raise_exceptions:
        raise ValueError(_(u'The username you entered could not be found.'))
    return member
    def add_to_aggregator(self,user_id=None,ignore_messages=False):
        """ add content to the user aggregator """
        message=None
        mtype=None
        if self._is_aggregable(user_id):
            #get an aggregator
            aggregator=self._find_aggregator(user_id)

            #add self.context
            if aggregator is not None:
                favorites = aggregator.getFavorites()
                if not self.context in favorites:
                    favorites.append(self.context)
                    aggregator.setFavorites(favorites)
                    if not ignore_messages:
                        message = _(u'plone_reader_message', default=u"Added in your aggregator")
                        mtype='info'
            elif not ignore_messages:
                message = _(u'plone_reader_aggregator_not_found', default=u"Is impossible to find an aggregator, create one first")
                mtype='error'
        elif not ignore_messages:
            message=_(u'plone_reader_not_aggregable',default=u"This content is not enabled to be added in an aggregator, check your configuration")
            mtype='error'

        redirect = self.request.response.redirect
        if message is not None:
            addMessage = IStatusMessage(self.request).addStatusMessage
            addMessage(message, type=mtype)

        redirect(self.context.absolute_url())
    def manageUser(self, users=None):
        if users is None:
            users = []
        CheckAuthenticator(self.request)

        if users:
            context = aq_inner(self.context)
            mtool = getToolByName(context, 'portal_membership')
            utils = getToolByName(context, 'plone_utils')

            unlocked = list()
            for user in users:
                if user['unlock']:
                    member = mtool.getMemberById(user.id)

                    member.setMemberProperties(
                        {'account_locked_date': DateTime('2000/01/01'),
                         'account_locked': False,
                         'password_tries': 0}
                    )
                    unlocked.append(user['id'])

                    notify(UserUnlocked(member))

            if unlocked:
                utils.addPortalMessage(
                    _(u'The following users were unlocked: %s'
                        % ', '.join(unlocked))
                )
            else:
                utils.addPortalMessage(_(u'No users were unlocked'))
Beispiel #23
0
 def __call__(self):
     context = self.context
     title = safe_unicode(context.title_or_id())
     if not has_permission('Copy or Move', context):
         msg = _(u'Permission denied to cut ${title}.',
                 mapping={u'title': title})
         msg = self.context.translate(msg)
         raise Unauthorized, msg
     try:
         lock_info = context.restrictedTraverse('plone_lock_info')
     except AttributeError:
         lock_info = None
     if lock_info is not None and lock_info.is_locked():
         msg = _(u'${title} is locked and cannot be cut.',
                 mapping={u'title': title})
         msg = self.context.translate(msg)
         raise Exception, msg
     parent = aq_parent(aq_inner(context))
     try:
         parent.manage_cutObjects(context.getId(), self.request)
     except CopyError:
         msg = _(u'${title} is not moveable.',
                 mapping={u'title': title})
         msg = self.context.translate(msg)
         raise Exception, msg
     self.request.response.setCookie('__fct', self.context.UID(), path='/')
     msg = _(u'${title} cut.', mapping={u'title': title})
     msg = self.context.translate(msg)
     transaction_note('Cut object %s' % context.absolute_url())
     return msg, None
Beispiel #24
0
    def validate_registration(self, action, data):
        """
        specific business logic for this join form
        note: all this logic was taken directly from the old
        validate_registration.py script in
        Products/CMFPlone/skins/plone_login/join_form_validate.vpy
        """

        # CSRF protection
        CheckAuthenticator(self.request)

        registration = getToolByName(self.context, 'portal_registration')

        errors = super(BaseRegistrationForm, self).validate(action, data)
        # ConversionErrors have no field_name attribute... :-(
        error_keys = [error.field_name for error in errors
                      if hasattr(error, 'field_name')]

        form_field_names = [f.field.getName() for f in self.form_fields]

        portal = getUtility(ISiteRoot)
        portal_props = getToolByName(self.context, 'portal_properties')
        props = portal_props.site_properties
        use_email_as_login = props.getProperty('use_email_as_login')

        # passwords should match
        if 'password' in form_field_names:
            assert('password_ctl' in form_field_names)
            # Skip this check if password fields already have an error
            if not ('password' in error_keys or \
                    'password_ctl' in error_keys):
                password = self.widgets['password'].getInputValue()
                password_ctl = self.widgets['password_ctl'].getInputValue()
                if password != password_ctl:
                    err_str = _(u'Passwords do not match.')
                    errors.append(WidgetInputError('password',
                                  u'label_password', err_str))
                    errors.append(WidgetInputError('password_ctl',
                                  u'label_password', err_str))
                    self.widgets['password'].error = err_str
                    self.widgets['password_ctl'].error = err_str

        # Password field should have a minimum length of 5
        if 'password' in form_field_names:
            # Skip this check if password fields already have an error
            if not 'password' in error_keys:
                password = self.widgets['password'].getInputValue()
                if password and len(password) < 5:
                    err_str = _(u'Passwords must contain at least 5 letters.')
                    errors.append(WidgetInputError(
                            'password', u'label_password', err_str))
                    self.widgets['password'].error = err_str

        username = ''
        email = ''
        try:
            email = self.widgets['email'].getInputValue()
        except InputErrors, exc:
            # WrongType?
            errors.append(exc)
    def renderItemsWithValues(self, values):
        """Render the list of possible values, with those found in
        `values` being marked as selected.

        This code is mostly taken from from zope.app.form.browser.itemswidgets
        import ItemsEditWidgetBase licensed under the ZPL 2.1.
        """

        cssClass = self.cssClass

        # multiple items with the same value are not allowed from a
        # vocabulary, so that need not be considered here
        rendered_items = []
        count = 0

        rendered_items.append(
            self._table_start_template
            % (
                self.translate(_(u"heading_allowed_languages", default=u"Allowed languages")),
                self.translate(_(u"heading_language_allowed", default=u"Allowed?")),
                self.translate(_(u"heading_language", default=u"Language")),
                self.translate(_(u"heading_language_code", default=u"Code")),
            )
        )

        # Handle case of missing value
        missing = self._toFormValue(self.context.missing_value)

        if self._displayItemForMissingValue and not self.context.required:
            if missing in values:
                render = self.renderSelectedItem
            else:
                render = self.renderItem

            missing_item = render(count, self.translate(self._messageNoValue), missing, self.name, cssClass)
            rendered_items.append(missing_item)
            count += 1

        # Render normal values
        vocabulary = [(self.textForValue(term), term) for term in self.vocabulary]

        # Sort by translated name, this is lame and needs proper collation
        # support, but we don't have that yet.
        vocabulary.sort()

        for item_text, term in vocabulary:
            if term.value in values:
                render = self.renderSelectedItem
            else:
                render = self.renderItem

            css = count % 2 and cssClass + "even" or cssClass + "odd"
            rendered_item = render(count, item_text, term.token, self.name, css)

            rendered_items.append(rendered_item)
            count += 1

        rendered_items.append(self._table_end_template)

        return rendered_items
    def object_cut(self, ajax=False):
        self.protect()
        context = aq_inner(self.context)
        title = self.objectTitle()
        plone_utils = getToolByName(context, 'plone_utils')
        lock_info = getMultiAdapter((context, self.request),
                                    name='plone_lock_info')
        if lock_info is not None and lock_info.is_locked():
            message = _(u'${title} is locked and cannot be cut.',
                mapping={u'title': title})
            plone_utils.addPortalMessage(message, 'error')
        else:
            parent = aq_parent(context)
            try:
                parent.manage_cutObjects(context.getId(), self.request)
                message = _(u'${title} cut.', mapping={u'title': title})
                utils.transaction_note('Cut object %s' % (
                    context.absolute_url()))
                plone_utils.addPortalMessage(message)
            except CopyError:
                message = _(u'${title} is not moveable.',
                    mapping={u'title': title})
                plone_utils.addPortalMessage(message, 'error')

        if ajax:
            pass
        else:
            return self.redirectReferer()
    def testPasswordValidity(self, password, confirm=None):

        """ Verify that the password satisfies the portal's requirements.

        o If the password is valid, return None.
        o If not, return a string explaining why.
        """
        if confirm is not None and confirm != password:
            return ( _(u'Your password and confirmation did not match. '
                   + 'Please try again.') )

        if not password:
            err = [ _(u'You must enter a password.') ]
        else:
            err = []

        # Use PAS to test validity
        pas_instance = self.acl_users
        plugins = pas_instance._getOb('plugins')
        validators = plugins.listPlugins(IValidationPlugin)
        for validator_id, validator in validators:
            user = None
            set_id = ''
            set_info = {'password':password}
            errors = validator.validateUserInfo( user, set_id, set_info )
            err += [info['error'] for info in errors if info['id'] == 'password' ]
        if err:
            return ' '.join(err)
        else:
            return None
Beispiel #28
0
 def execute(self):
     if anon():
         raise Unauthorized, u'Not authenticated'
     name = self.request.get(u'name', u'')
     uid = self.uid
     context = self._execution_context()
     if not context:
         msg = _(u'Object not found. Could not continue.')
         return json.dumps({
             'err': True,
             'msg': self.context.translate(msg),
         })
     err = False
     ret_uid = None
     try:
         toadapt = (context, self.request)
         msg, ret_uid = getMultiAdapter(toadapt, IAction, name=name)()
         if ret_uid is None:
             ret_uid = uid
     except ComponentLookupError, e:
         err = True
         msg = _(u'No such action: ${name} for ${uid}.',
                 mapping={
                     u'name': name,
                     u'uid': uid,
                 })
         msg = self.context.translate(msg)
    def object_rename(self):
        self.protect()
        context = aq_inner(self.context)
        plone_utils = getToolByName(context, 'plone_utils')
        title = self.objectTitle()
        referer = self.request.get('HTTP_REFERER')
        new_ids = self.request.get('new_ids')
        new_titles = self.request.get('new_titles')
        paths = self.request.get('paths')
        message = _(u'"${title}" could not be renamed: Unknown Error.',
                mapping={u'title': title})
        old_id = context.id
        
        success, failure = putils.renameObjectsByPaths(paths, new_ids, new_titles,
                                               REQUEST=request)

        if failure:
            message = _(u'The item could not be renamed: ${items}.',
                mapping={u'items': ', '.join(failure.keys())})
            plone_utils.addPortalMessage(message)
        elif len(success):
            message = _(u"Renamed '${oldid}' to '${newid}'.",
                mapping={u'oldid': old_id, u'newid': new_ids[0]})
            redirect_url =
            plone_utils.addPortalMessage(message)
            redirect_url = "/".join(self.context.getPhysicalPath()[1:-1] + [new_id])
            return request.response.redirect(redirect_url)
        
        return self.redirectReferer()
Beispiel #30
0
 def handle_edit_action(self, action, data):
     CheckAuthenticator(self.request)
     if form.applyChanges(self.context, self.form_fields, data, self.adapters):
         self.status = _("Changes saved.")
         self._on_save(data)
     else:
         self.status = _("No changes made.")
class ISponsor(Interface):
    """An object which contains contains information related to sponsors, displayed on the site.
    """

    title = schema.TextLine(title=_(u"Object title"), required=True)
class IQuestion(Interface):
    """An folder objects which contains object belong to a tutorial such as lectures and sponsors.
    """

    title = schema.TextLine(title=_(u"Object title"), required=True)
class IClass(Interface):
    """An object which describes classes belonging to a specific school.
    """
    title = schema.TextLine(title=_(u"Object title"), required=True)
class IDatabaseSettings(Interface):
    """Database connection settings.
    """

    drivername = schema.ASCIILine(title=_(u"Driver name"),
                                  description=_(u"The database driver name"),
                                  default='mysql',
                                  required=True)

    hostname = schema.ASCIILine(title=_(u"Host name"),
                                description=_(u"The database host name"),
                                default='localhost',
                                required=True)

    port = schema.Int(
        title=_(u"Port number"),
        description=_(
            u"The database port number. Leave blank to use the default."),
        required=False)

    username = schema.ASCIILine(title=_(u"User name"),
                                description=_(u"The database user name"),
                                required=True)

    password = schema.Password(title=_(u"Password"),
                               description=_(u"The database password"),
                               required=False)

    database = schema.ASCIILine(
        title=_(u"Database name"),
        description=_(u"The name of the database on this server"),
        required=True)
class IOrderedTutorWebContent(Interface):
    """TutorWeb ordered content and by default is published, or available for viewing to anonymous or logged on users
    """

    title = schema.TextLine(title=_(u"Object title"), required=True)
class IPrintable(Interface):
    """An object which contains content wich can be printed to a pdf document.
    Should it be part of tutorial????
    """

    title = schema.TextLine(title=_(u"Object title"), required=True)
class IStudentList(Interface):
    """An object which contains informatio concerning a student taking a test.
    """
    title = schema.TextLine(title=_(u"Object title"), required=True)
Beispiel #38
0
class DeleteConfirmationForm(actions.DeleteConfirmationForm):

    template = ViewPageTemplateFile('templates/delete_confirmation.pt')

    @property
    @memoize
    def items_to_delete(self):
        catalog = getToolByName(self.context, 'portal_catalog')
        results = catalog({'path': '/'.join(self.context.getPhysicalPath())})
        return len(results)

    def more_info(self):
        if self.items_to_delete > 120:
            IStatusMessage(self.request).add(
                """
You have selected to delete %i items which is a large amount.
This action can take a long time to accomplish. We will email you
when the content is done being deleted.""" % self.items_to_delete, 'error')
        else:
            return super(DeleteConfirmationForm, self).more_info()

    @property
    def is_locked(self):
        return is_locked(self)

    @button.buttonAndHandler(_(u'Delete'), name='Delete')
    def handle_delete(self, action):
        title = safe_unicode(self.context.Title())
        parent = aq_parent(aq_inner(self.context))

        # has the context object been acquired from a place it should not have
        # been?
        if self.context.aq_chain == self.context.aq_inner.aq_chain:
            if self.items_to_delete > 120:
                tasks.delete_items.delay([IUUID(self.context)])
                IStatusMessage(self.request).add(
                    """
You have selected to delete %i items which is a large amount.
This action can take a long time to accomplish. We will email you
when the content is done being deleted.""" % self.items_to_delete, 'error')
            else:
                if self.is_locked:
                    # force unlock before delete...
                    lockable = ILockable(self.context)
                    lockable.clear_locks()

                parent.manage_delObjects(self.context.getId(), self.request)
                IStatusMessage(self.request).add(
                    _(u'${title} has been deleted.', mapping={u'title':
                                                              title}))
        else:
            IStatusMessage(self.request).add(
                _(u'"${title}" has already been deleted',
                  mapping={u'title': title}))

        self.request.response.redirect(parent.absolute_url())

    @property
    def items_to_trash(self):
        catalog = getToolByName(self.context, 'portal_catalog')
        putils = getToolByName(self.context, 'plone_utils')
        results = catalog({
            'path': '/'.join(self.context.getPhysicalPath()),
            'portal_type': putils.getUserFriendlyTypes(),
        })
        return len(results)

    @button.buttonAndHandler(u'Move to recycle bin', name='Move')
    def handle_move(self, action):
        title = safe_unicode(self.context.Title())
        parent = aq_parent(aq_inner(self.context))

        # has the context object been acquired from a place it should not have
        # been?
        if self.context.aq_chain == self.context.aq_inner.aq_chain:
            trash.object(self.context)
            IStatusMessage(self.request).add(
                u'%s has been moved to recycle bin.' % title)

        self.request.response.redirect(parent.absolute_url())

    @button.buttonAndHandler(u'Cancel', name='Cancel')
    def handle_cancel(self, action):
        utils = Utils(self.context, self.request)
        target = utils.get_object_url(self.context)
        return self.request.response.redirect(target)
Beispiel #39
0
class TypesControlPanel(AutoExtensibleForm, form.EditForm):
    schema = ITypesSchema
    id = "types-control-panel"
    label = _("Types Settings")
    description = _("General types settings.")
    form_name = _("Types settings")
    control_panel_view = "content-controlpanel"
    template = ViewPageTemplateFile('types.pt')
    behavior_name = 'plone.app.versioningbehavior.behaviors.IVersionable'

    @button.buttonAndHandler(_('Save'), name='save')
    def handleSave(self, action):
        data, errors = self.extractData()
        if errors:
            self.status = self.formErrorsMessage
            return
        IStatusMessage(self.request).addStatusMessage(_("Changes saved"),
                                                      "info")
        self.request.response.redirect("@@content-controlpanel")

    @button.buttonAndHandler(_("Cancel"), name='cancel')
    def handleCancel(self, action):
        IStatusMessage(self.request).addStatusMessage(_("Changes canceled."),
                                                      "info")
        self.request.response.redirect("@@overview-controlpanel")

    @property
    @memoize
    def type_id(self):
        type_id = self.request.get('type_id', None)
        if type_id is None:
            type_id = ''
        return type_id

    @property
    @memoize
    def fti(self):
        type_id = self.type_id
        portal_types = getToolByName(self.context, 'portal_types')
        return getattr(portal_types, type_id)

    def add_versioning_behavior(self, fti):
        if not IDexterityFTI.providedBy(fti):
            return
        behaviors = list(fti.behaviors)
        if self.behavior_name not in behaviors:
            behaviors.append(self.behavior_name)
        # locking must be turned on for versioning support on the type
        locking = 'plone.app.lockingbehavior.behaviors.ILocking'
        if locking not in behaviors:
            behaviors.append(locking)

        fti.behaviors = behaviors

    def remove_versioning_behavior(self, fti):
        if not IDexterityFTI.providedBy(fti):
            return
        behaviors = list(fti.behaviors)
        if self.behavior_name in behaviors:
            behaviors.remove(self.behavior_name)
        # TODO: remove locking if it wasn't set in first place
        fti.behaviors = behaviors

    def __call__(self):
        """Perform the update and redirect if necessary, or render the page
        """
        postback = True
        context = aq_inner(self.context)

        form = self.request.form
        submitted = form.get('form.submitted', False)
        save_button = form.get('form.button.Save', None) is not None
        cancel_button = form.get('form.button.Cancel', None) is not None
        type_id = form.get('old_type_id', None)

        if save_button and submitted and not cancel_button:
            if type_id:
                portal_types = getToolByName(self.context, 'portal_types')
                portal_repository = getToolByName(self.context,
                                                  'portal_repository')

                fti = getattr(portal_types, type_id)

                # Set FTI properties

                addable = form.get('addable', False)
                allow_discussion = form.get('allow_discussion', False)

                fti.manage_changeProperties(
                    global_allow=bool(addable),
                    allow_discussion=bool(allow_discussion))

                version_policy = form.get('versionpolicy', "off")
                if version_policy != self.current_versioning_policy():
                    newpolicy = [
                        p for p in VERSION_POLICIES
                        if p["id"] == version_policy
                    ][0]

                    versionable_types = list(
                        portal_repository.getVersionableContentTypes())
                    if not newpolicy["policy"]:
                        # check if we need to remove
                        if type_id in versionable_types:
                            versionable_types.remove(type_id)
                        self.remove_versioning_behavior(fti)
                    else:
                        # check if we should add
                        if type_id not in versionable_types:
                            versionable_types.append(safe_unicode(type_id))
                        self.add_versioning_behavior(fti)

                    for policy in portal_repository.listPolicies():
                        policy_id = policy.getId()
                        if policy_id in newpolicy["policy"]:
                            portal_repository.addPolicyForContentType(
                                type_id, policy_id)
                        else:
                            portal_repository.removePolicyFromContentType(
                                type_id, policy_id)

                    portal_repository.setVersionableContentTypes(
                        versionable_types)

                # Set Registry-entries
                registry = getUtility(IRegistry)

                searchable = form.get('searchable', False)
                site_settings = registry.forInterface(ISearchSchema,
                                                      prefix="plone")
                blacklisted = [i for i in site_settings.types_not_searched]
                if searchable and type_id in blacklisted:
                    blacklisted.remove(type_id)
                elif not searchable and type_id not in blacklisted:
                    blacklisted.append(type_id)
                site_settings.types_not_searched = tuple(blacklisted)

                default_page_type = form.get('default_page_type', False)
                types_settings = registry.forInterface(ITypesSchema,
                                                       prefix="plone")
                default_page_types = [
                    safe_unicode(i) for i in types_settings.default_page_types
                ]
                if default_page_type and type_id not in default_page_types:
                    default_page_types.append(safe_unicode(type_id))
                elif not default_page_type and type_id in default_page_types:
                    default_page_types.remove(type_id)
                types_settings.default_page_types = default_page_types
                if type_id == 'Link':
                    redirect_links = form.get('redirect_links', False)
                    types_settings.redirect_links = redirect_links

            # Update workflow
            if self.have_new_workflow() \
                    and form.get('form.workflow.submitted', False) \
                    and save_button:
                if self.new_workflow_is_different():
                    new_wf = self.new_workflow()
                    if new_wf == '[none]':
                        chain = ()
                    elif new_wf == '(Default)':
                        chain = new_wf
                    else:
                        chain = (new_wf, )
                    state_map = {
                        s['old_state']: s['new_state']
                        for s in form.get('new_wfstates', [])
                    }
                    if '[none]' in state_map:
                        state_map[None] = state_map['[none]']
                        del state_map['[none]']
                    if type_id:
                        type_ids = (type_id, )
                    else:
                        wt = getToolByName(self.context, 'portal_workflow')
                        tt = getToolByName(self.context, 'portal_types')
                        nondefault = [
                            info[0] for info in wt.listChainOverrides()
                        ]
                        type_ids = [
                            type for type in tt.listContentTypes()
                            if type not in nondefault
                        ]
                        wt.setChainForPortalTypes(type_ids,
                                                  wt.getDefaultChain())
                        wt.setDefaultChain(','.join(chain))
                        chain = '(Default)'

                    remap_workflow(context,
                                   type_ids=type_ids,
                                   chain=chain,
                                   state_map=state_map)

                    data = {'workflow': new_wf}
                    notify(ConfigurationChangedEvent(self, data))

                else:
                    portal_workflow = getToolByName(context, 'portal_workflow')
                    if self.new_workflow() == '(Default)':
                        # The WorkflowTool API can not handle this sanely
                        cbt = portal_workflow._chains_by_type
                        if type_id in cbt:
                            del cbt[type_id]
                    else:
                        portal_workflow.setChainForPortalTypes(
                            (type_id, ), self.new_workflow())

                self.request.response.redirect(
                    '{}/@@content-controlpanel?type_id={}'.format(
                        context.absolute_url(), type_id))
                postback = False

        elif cancel_button:
            self.request.response.redirect(self.context.absolute_url() +
                                           '/@@overview-controlpanel')
            postback = False

        if postback:
            return self.template()

    # View

    def versioning_policies(self):
        return VERSION_POLICIES

    @memoize
    def selectable_types(self):
        vocab_factory = getUtility(
            IVocabularyFactory,
            name="plone.app.vocabularies.ReallyUserFriendlyTypes")
        types = []
        for v in vocab_factory(self.context):
            if v.title:
                title = translate(v.title, context=self.request)
            else:
                title = translate(v.token,
                                  domain='plone',
                                  context=self.request)
            types.append(dict(id=v.value, title=title))

        types.sort(key=itemgetter('title'))
        return types

    def selected_type_title(self):
        return self.fti.Title()

    def selected_type_description(self):
        return self.fti.Description()

    def is_addable(self):
        return self.fti.getProperty('global_allow', False)

    def is_discussion_allowed(self):
        return self.fti.getProperty('allow_discussion', False)

    def current_versioning_policy(self):
        portal_repository = getToolByName(self.context, 'portal_repository')
        if self.type_id not in portal_repository.getVersionableContentTypes():
            return "off"
        policy = set(portal_repository.getPolicyMap().get(self.type_id, ()))
        for info in VERSION_POLICIES:
            if set(info["policy"]) == policy:
                return info["id"]
        return None

    def is_searchable(self):
        registry = getUtility(IRegistry)
        settings = registry.forInterface(ISearchSchema, prefix="plone")
        blacklisted = settings.types_not_searched
        return (self.type_id not in blacklisted)

    def is_default_page_type(self):
        registry = getUtility(IRegistry)
        settings = registry.forInterface(ITypesSchema, prefix="plone")
        return self.type_id in settings.default_page_types

    def is_redirect_links_enabled(self):
        if self.type_id == 'Link':
            registry = getUtility(IRegistry)
            settings = registry.forInterface(ITypesSchema, prefix="plone")
            return settings.redirect_links
        return False

    @memoize
    def current_workflow(self):
        context = aq_inner(self.context)
        portal_workflow = getToolByName(context, 'portal_workflow')
        default_workflow = self.default_workflow(False)
        nondefault = [info[0] for info in portal_workflow.listChainOverrides()]
        chain = portal_workflow.getChainForPortalType(self.type_id)
        empty_workflow_dict = dict(
            id='[none]',
            title=_("label_no_workflow"),
            description=[
                _("description_no_workflow",
                  default="This type has no workflow. The visibilty "
                  "of items of this type is determined by "
                  "the folder they are in.")
            ])

        if self.type_id in nondefault:
            if chain:
                wf_id = chain[0]
                wf = getattr(portal_workflow, wf_id)
                title = translate(safe_unicode(wf.title),
                                  domain='plone',
                                  context=self.request)
                return dict(id=wf.id,
                            title=title,
                            description=format_description(
                                safe_unicode(wf.description), self.request))
            else:
                return empty_workflow_dict

        if default_workflow == '[none]':
            return empty_workflow_dict

        default_title = translate(safe_unicode(default_workflow.title),
                                  domain='plone',
                                  context=self.request)
        return dict(id='(Default)',
                    title=_("label_default_workflow_title",
                            default="Default workflow (${title})",
                            mapping=dict(title=default_title)),
                    description=format_description(
                        default_workflow.description, self.request))

    def available_workflows(self):
        vocab_factory = getUtility(IVocabularyFactory,
                                   name="plone.app.vocabularies.Workflows")
        workflows = []
        for v in vocab_factory(self.context):
            if v.title:
                title = translate(v.title, context=self.request)
            else:
                title = translate(v.token,
                                  domain='plone',
                                  context=self.request)
            workflows.append(dict(id=v.value, title=title))

        workflows.sort(key=itemgetter('title'))

        default_workflow = self.default_workflow(False)
        if self.type_id and default_workflow != '[none]':
            # Only offer a default workflow option on a real type
            default_workflow = self.default_workflow(False)
            default_title = translate(safe_unicode(default_workflow.title),
                                      domain='plone',
                                      context=self.request)
            workflows.insert(
                0,
                dict(id='(Default)',
                     title=_("label_default_workflow_title",
                             default="Default workflow (${title})",
                             mapping=dict(title=default_title)),
                     description=format_description(
                         default_workflow.description, self.request)))

        return workflows

    @memoize
    def new_workflow(self):
        current_workflow = self.current_workflow()['id']
        if self.type_id == '':
            # If we are looking at the default workflow we need to show
            # the real workflow
            current_workflow = self.real_workflow(current_workflow)
        old_type_id = self.request.form.get('old_type_id', self.type_id)
        if old_type_id != self.type_id:
            return current_workflow
        else:
            return self.request.form.get('new_workflow', current_workflow)

    @memoize
    def have_new_workflow(self):
        return self.current_workflow()['id'] != self.new_workflow()

    @memoize
    def default_workflow(self, id_only=True):
        portal_workflow = getToolByName(self.context, 'portal_workflow')
        default_chain = portal_workflow.getDefaultChain()
        if not default_chain:
            # There is no default workflow
            return '[none]'
        id = default_chain[0]
        if id_only:
            return id
        else:
            return portal_workflow.getWorkflowById(id)

    @memoize
    def real_workflow(self, wf):
        if wf == '(Default)':
            return self.default_workflow()
        else:
            return wf

    @memoize
    def new_workflow_is_different(self):
        new_workflow = self.new_workflow()
        current_workflow = self.current_workflow()['id']

        return self.real_workflow(new_workflow) != self.real_workflow(
            current_workflow)

    @memoize
    def new_workflow_is_none(self):
        return self.new_workflow() == '[none]'

    def new_workflow_description(self):
        portal_workflow = getToolByName(self.context, 'portal_workflow')
        new_workflow = self.new_workflow()

        if self.new_workflow_is_different():
            if self.new_workflow_is_none():
                return [
                    _("description_no_workflow",
                      default="This type has no workflow. The visibilty of "
                      "items of this type is determined by the "
                      "folder they are in.")
                ]
            new_workflow = self.real_workflow(self.new_workflow())
            wf = getattr(portal_workflow, new_workflow)
            return format_description(wf.description, self.request)

        return None

    def new_workflow_available_states(self):
        if self.new_workflow_is_different():
            new_workflow = self.real_workflow(self.new_workflow())
            portal_workflow = getToolByName(self.context, 'portal_workflow')
            wf = getattr(portal_workflow, new_workflow)
            states = []
            for s in wf.states.objectValues():
                title = translate(s.title,
                                  domain='plone',
                                  context=self.request)
                states.append(dict(id=s.id, title=title))
            return states
        else:
            return []

    def suggested_state_map(self):
        current_workflow = self.real_workflow(self.current_workflow()['id'])
        new_workflow = self.real_workflow(self.new_workflow())

        portal_workflow = getToolByName(self.context, 'portal_workflow')

        if current_workflow == '[none]':
            new_wf = getattr(portal_workflow, new_workflow)
            default_state = new_wf.initial_state
            return [
                dict(old_id='[none]',
                     old_title=_("No workflow"),
                     suggested_id=default_state)
            ]

        elif self.new_workflow_is_different():
            old_wf = getattr(portal_workflow, current_workflow)
            new_wf = getattr(portal_workflow, new_workflow)

            new_states = {s.id for s in new_wf.states.objectValues()}
            default_state = new_wf.initial_state

            states = []
            for old in old_wf.states.objectValues():
                title = translate(old.title,
                                  domain='plone',
                                  context=self.request)
                states.append(
                    dict(old_id=old.id,
                         old_title=title,
                         suggested_id=(old.id in new_states and old.id
                                       or default_state)))
            return states
        else:
            return []
class IBaseQuestionSelectionParameters(Interface):
    """An object which contains information conerning how questions are selected in a quiz.
    """

    title = schema.TextLine(title=_(u"Object title"), required=True)
 def send_feedback(self):
     IStatusMessage(self.request).add(
         _(u'A mail has now been sent to the site administrator '
           u'regarding your questions and/or comments.'))
Beispiel #42
0
 def handleCancel(self, action):
     IStatusMessage(self.request).addStatusMessage(_("Changes canceled."),
                                                   "info")
     self.request.response.redirect("@@overview-controlpanel")
Beispiel #43
0
 class JSONError(schema.ValidationError):
     __doc__ = _(
         u"Must be empty or a valid JSON-formatted "
         u"configuration – ${message}.",
         mapping={'message': six.text_type(exc)})
Beispiel #44
0
from zope.i18n import translate
from zope.schema.interfaces import IVocabularyFactory
from plone.dexterity.interfaces import IDexterityFTI


def format_description(text, request=None):
    # We expect the workflow to be a text of '- ' divided bullet points.
    text = translate(text.strip(), domain='plone', context=request)
    return [s.strip() for s in text.split('- ') if s]


# These are convenient / user friendly versioning policies.
VERSION_POLICIES = [
    dict(id="off",
         policy=(),
         title=_("versioning_off", default="No versioning")),
    dict(id="manual",
         policy=("version_on_revert", ),
         title=_("versioning_manual", default="Manual")),
    dict(id="automatic",
         policy=("at_edit_autoversion", "version_on_revert"),
         title=_("versioning_automatic", default="Automatic")),
]


class TypesControlPanel(AutoExtensibleForm, form.EditForm):
    schema = ITypesSchema
    id = "types-control-panel"
    label = _("Types Settings")
    description = _("General types settings.")
    form_name = _("Types settings")
Beispiel #45
0
 def handle_clearall_action(self, action, data):
     CheckAuthenticator(self.request)
     getUtility(IRAMCache).invalidateAll()
     self.status = _(u'Cleared the cache.')
Beispiel #46
0
def check_id(context,
             id=None,
             required=0,
             alternative_id=None,
             contained_by=None,
             **kwargs):
    """Test an id to make sure it is valid.

    This used to be in Products/CMFPlone/skins/plone_scripts/check_id.py.

    Returns an error message if the id is bad or None if the id is good.
    Parameters are as follows:

        id - the id to check

        required - if False, id can be the empty string

        alternative_id - an alternative value to use for the id
        if the id is empty or autogenerated

    Accept keyword arguments for compatibility with the fallback
    in Products.validation.

    Note: The reason the id is included is to handle id error messages for
    such objects as files and images that supply an alternative id when an
    id is auto-generated.
    If you say "There is already an item with this name in this folder"
    for an image that has the Name field populated with an autogenerated id,
    it can cause some confusion; since the real problem is the name of
    the image file name, not in the name of the autogenerated id.
    """
    def xlate(message):
        ts = getToolByName(context, 'translation_service', None)
        if ts is None:
            return message
        return ts.translate(message, context=context.REQUEST)

    # if an alternative id has been supplied, see if we need to use it
    if alternative_id and not id:
        id = alternative_id

    # make sure we have an id if one is required
    if not id:
        if required:
            return xlate(_(u'Please enter a name.'))

        # Id is not required and no alternative was specified, so assume the
        # object's id will be context.getId(). We still should check to make
        # sure context.getId() is OK to handle the case of pre-created objects
        # constructed via portal_factory.  The main potential problem is an id
        # collision, e.g. if portal_factory autogenerates an id that already
        # exists.

        id = context.getId()

    #
    # do basic id validation
    #

    # check for reserved names
    if id in (
            'login',
            'layout',
            'plone',
            'zip',
            'properties',
    ):
        return xlate(_(u'${name} is reserved.', mapping={'name': id}))

    # check for bad characters
    plone_utils = getToolByName(context, 'plone_utils', None)
    if plone_utils is not None:
        bad_chars = plone_utils.bad_chars(id)
        if len(bad_chars) > 0:
            bad_chars = ''.join(bad_chars).decode('utf-8')
            decoded_id = id.decode('utf-8')
            return xlate(
                _(
                    u'${name} is not a legal name. The following characters are '
                    u'invalid: ${characters}',
                    mapping={
                        u'name': decoded_id,
                        u'characters': bad_chars
                    }))

    # check for a catalog index
    portal_catalog = getToolByName(context, 'portal_catalog', None)
    if portal_catalog is not None:
        if id in list(portal_catalog.indexes()) + list(
                portal_catalog.schema()):
            return xlate(_(u'${name} is reserved.', mapping={u'name': id}))

    # id is good; decide if we should check for id collisions
    portal_factory = getToolByName(context, 'portal_factory', None)
    if contained_by is not None:
        # Always check for collisions if a container was passed
        # via the contained_by parameter.
        checkForCollision = True
    elif portal_factory is not None and portal_factory.isTemporary(context):
        # always check for collisions if we are creating a new object
        checkForCollision = True
        # Climb the acquisition chain until you get at the real container.
        contained_by = aq_parent(aq_parent(aq_parent(aq_inner(context))))
    else:
        # if we have an existing object, only check for collisions
        # if we are changing the id
        checkForCollision = (context.getId() != id)

    # check for id collisions
    if not checkForCollision:
        # We are done.
        return
    # handles two use cases:
    # 1. object has not yet been created and we don't know where it will be
    # 2. object has been created and checking validity of id within
    #    container
    if contained_by is None:
        try:
            contained_by = context.getParentNode()
        except Unauthorized:
            return  # nothing we can do
    try:
        result = _check_for_collision(contained_by, id, **kwargs)
    except Unauthorized:
        # There is a permission problem. Safe to assume we can't use this id.
        return xlate(_(u'${name} is reserved.', mapping={u'name': id}))
    if result is not None:
        result = xlate(result, )
    return result
Beispiel #47
0
class EditForm(base.EditForm):
    schema = ITileInterface

    label = _(u"Edit Office Address Information Portlet")
    description = _(u"This portlet displays office address information.")
Beispiel #48
0
def _check_for_collision(contained_by, id, **kwargs):
    """Check for collisions of an object id in a container.

    Accept keyword arguments for compatibility with the fallback
    in Products.validation.

    When this was still a Python skin script, some security checks
    would have been done automatically and caught by some
    'except Unauthorized' lines.  Now, in unrestricted Python
    code, we explicitly check.  But not all checks make sense.  If you don't
    have the 'Access contents information' permission, theoretically
    you should not be able to check for an existing conflicting id,
    but it seems silly to then pretend that there is no conflict.

    For safety, we let the check_id
    function do a try/except Unauthorized when calling us.
    """
    secman = getSecurityManager()
    # if not secman.checkPermission(
    #         'Access contents information', contained_by):
    #     # We cannot check.  Do not complain.
    #     return

    # Check for an existing object.
    if id in contained_by:
        existing_obj = getattr(contained_by, id, None)
        if base_hasattr(existing_obj, 'portal_type'):
            return _(u'There is already an item named ${name} in this folder.',
                     mapping={u'name': id})

    if base_hasattr(contained_by, 'checkIdAvailable'):
        # This used to be called from the check_id skin script,
        # which would check the permission automatically,
        # and the code would catch the Unauthorized exception.
        if secman.checkPermission(AddPortalContent, contained_by):
            if not contained_by.checkIdAvailable(id):
                return _(u'${name} is reserved.', mapping={u'name': id})

    # containers may implement this hook to further restrict ids
    if base_hasattr(contained_by, 'checkValidId'):
        try:
            contained_by.checkValidId(id)
        except ConflictError:
            raise
        except:  # noqa: E722
            return _(u'${name} is reserved.', mapping={u'name': id})

    # make sure we don't collide with any parent method aliases
    plone_utils = getToolByName(contained_by, 'plone_utils', None)
    portal_types = getToolByName(contained_by, 'portal_types', None)
    if plone_utils is not None and portal_types is not None:
        parentFti = portal_types.getTypeInfo(contained_by)
        if parentFti is not None:
            aliases = plone_utils.getMethodAliases(parentFti)
            if aliases is not None:
                if id in aliases.keys():
                    return _(u'${name} is reserved.', mapping={u'name': id})

    # Lastly, we want to disallow the id of any of the tools in the portal
    # root, as well as any object that can be acquired via portal_skins.
    # However, we do want to allow overriding of *content* in the object's
    # parent path, including the portal root.

    if id == 'index_html':
        # always allow index_html
        return
    portal_url = getToolByName(contained_by, 'portal_url', None)
    if portal_url is None:
        # Probably a test.
        # All other code needs the portal, so there is nothing left to check.
        return
    portal = portal_url.getPortalObject()
    if id in portal.contentIds():
        # Fine to use the same id as a *content* item from the root.
        return
    # It is allowed to give an object the same id as another
    # container in it's acquisition path as long as the
    # object is outside the portal.
    outsideportal = getattr(aq_parent(portal), id, None)
    insideportal = getattr(portal, id, None)
    if (insideportal is not None and outsideportal is not None
            and aq_base(outsideportal) == aq_base(insideportal)):
        return
    # but not other things
    if getattr(portal, id, None) is not None:
        return _(u'${name} is reserved.', mapping={u'name': id})
Beispiel #49
0
class PloneControlPanel(PloneBaseTool, UniqueObject, Folder,
                        ActionProviderBase, PropertyManager):
    """Weave together the various sources of "actions" which
    are apropos to the current user and context.
    """

    security = ClassSecurityInfo()

    id = 'portal_controlpanel'
    title = 'Control Panel'
    toolicon = 'skins/plone_images/site_icon.png'
    meta_type = 'Plone Control Panel Tool'
    _actions_form = DTMLFile('www/editPloneConfiglets', globals())

    manage_options = (ActionProviderBase.manage_options +
                      PropertyManager.manage_options)

    group = dict(member=[
        ('Member', _(u'My Preferences')),
    ],
                 site=[
                     ('plone-general', _(u'General')),
                     ('plone-content', _(u'Content')),
                     ('plone-users', _(u'Users')),
                     ('plone-security', _(u'Security')),
                     ('plone-advanced', _(u'Advanced')),
                     ('Plone', _(u'Plone Configuration')),
                     ('Products', _(u'Add-on Configuration')),
                 ])

    def __init__(self, **kw):
        if kw:
            self.__dict__.update(**kw)

    security.declareProtected(ManagePortal, 'registerConfiglets')

    def registerConfiglets(self, configlets):
        for conf in configlets:
            self.registerConfiglet(**conf)

    security.declareProtected(ManagePortal, 'getGroupIds')

    def getGroupIds(self, category='site'):
        groups = self.group.get(category, [])
        return [g[0] for g in groups if g]

    security.declareProtected(View, 'getGroups')

    def getGroups(self, category='site'):
        groups = self.group.get(category, [])
        return [{'id': g[0], 'title': g[1]} for g in groups if g]

    security.declarePrivate('listActions')

    def listActions(self, info=None, object=None):
        # This exists here to shut up a deprecation warning about old-style
        # actions in CMFCore's ActionProviderBase.  It was decided not to
        # move configlets to be based on action tool categories for Plone 4
        # (see PLIP #8804), but that (or an alternative) will have to happen
        # before CMF 2.4 when support for old-style actions is removed.
        return self._actions or ()

    security.declarePublic('maySeeSomeConfiglets')

    def maySeeSomeConfiglets(self):
        groups = self.getGroups('site')

        all = []
        for group in groups:
            all.extend(self.enumConfiglets(group=group['id']))
        all = [item for item in all if item['visible']]
        return len(all) != 0

    security.declarePublic('enumConfiglets')

    def enumConfiglets(self, group=None):
        portal = getToolByName(self, 'portal_url').getPortalObject()
        context = createExprContext(self, portal, self)
        res = []
        for a in self.listActions():
            verified = 0
            for permission in a.permissions:
                if _checkPermission(permission, portal):
                    verified = 1
            if verified and a.category == group and a.testCondition(context) \
                    and a.visible:
                res.append(a.getAction(context))
        # Translate the title for sorting
        if getattr(self, 'REQUEST', None) is not None:
            for a in res:
                title = a['title']
                if not isinstance(title, Message):
                    title = Message(title, domain='plone')
                a['title'] = translate(title, context=self.REQUEST)

        def _id(v):
            return v['id']

        res.sort(key=_id)
        return res

    security.declareProtected(ManagePortal, 'unregisterConfiglet')

    def unregisterConfiglet(self, id):
        actids = [o.id for o in self.listActions()]
        selection = [actids.index(a) for a in actids if a == id]
        if not selection:
            return
        self.deleteActions(selection)

    security.declareProtected(ManagePortal, 'unregisterApplication')

    def unregisterApplication(self, appId):
        acts = list(self.listActions())
        selection = [acts.index(a) for a in acts if a.appId == appId]
        if not selection:
            return
        self.deleteActions(selection)

    def _extractAction(self, properties, index):
        # Extract an ActionInformation from the funky form properties.
        id = str(properties.get('id_%d' % index, ''))
        name = str(properties.get('name_%d' % index, ''))
        action = str(properties.get('action_%d' % index, ''))
        condition = str(properties.get('condition_%d' % index, ''))
        category = str(properties.get('category_%d' % index, ''))
        visible = properties.get('visible_%d' % index, 0)
        permissions = properties.get('permission_%d' % index, ())
        appId = properties.get('appId_%d' % index, '')
        description = properties.get('description_%d' % index, '')
        icon_expr = properties.get('icon_expr_%d' % index, '')

        if not name:
            raise ValueError('A name is required.')

        if action is not '':
            action = Expression(text=action)

        if condition is not '':
            condition = Expression(text=condition)

        if category == '':
            category = 'object'

        if not isinstance(visible, int):
            try:
                visible = int(visible)
            except ValueError:
                visible = 0

        if isinstance(permissions, six.string_types):
            permissions = (permissions, )

        return PloneConfiglet(
            id=id,
            title=name,
            action=action,
            condition=condition,
            permissions=permissions,
            category=category,
            visible=visible,
            appId=appId,
            description=description,
            icon_expr=icon_expr,
        )

    security.declareProtected(ManagePortal, 'addAction')

    def addAction(
        self,
        id,
        name,
        action,
        condition='',
        permission='',
        category='Plone',
        visible=1,
        appId=None,
        icon_expr='',
        description='',
        REQUEST=None,
    ):
        # Add an action to our list.
        if not name:
            raise ValueError('A name is required.')

        a_expr = action and Expression(text=str(action)) or ''
        c_expr = condition and Expression(text=str(condition)) or ''

        if not isinstance(permission, tuple):
            permission = permission and (str(permission), ) or ()

        new_actions = self._cloneActions()

        new_action = PloneConfiglet(
            id=str(id),
            title=name,
            action=a_expr,
            condition=c_expr,
            permissions=permission,
            category=str(category),
            visible=int(visible),
            appId=appId,
            description=description,
            icon_expr=icon_expr,
        )

        new_actions.append(new_action)
        self._actions = tuple(new_actions)

        if REQUEST is not None:
            return self.manage_editActionsForm(REQUEST,
                                               manage_tabs_message='Added.')

    security.declareProtected(ManagePortal, 'registerConfiglet')
    registerConfiglet = addAction

    security.declareProtected(ManagePortal, 'manage_editActionsForm')

    def manage_editActionsForm(self, REQUEST, manage_tabs_message=None):
        """ Show the 'Actions' management tab.
        """
        actions = []

        for a in self.listActions():

            a1 = {}
            a1['id'] = a.getId()
            a1['name'] = a.Title()
            p = a.getPermissions()
            if p:
                a1['permission'] = p[0]
            else:
                a1['permission'] = ''
            a1['category'] = a.getCategory() or 'object'
            a1['visible'] = a.getVisibility()
            a1['action'] = a.getActionExpression()
            a1['condition'] = a.getCondition()
            a1['appId'] = a.getAppId()
            a1['description'] = a.getDescription()
            a1['icon_expr'] = a.getIconExpression()
            actions.append(a1)

        # possible_permissions is in OFS.role.RoleManager.
        pp = self.possible_permissions()
        return self._actions_form(
            self,
            REQUEST,
            actions=actions,
            possible_permissions=pp,
            management_view='Actions',
            manage_tabs_message=manage_tabs_message,
        )

    @property
    def site_url(self):
        """Return the absolute URL to the current site, which is likely not
        necessarily the portal root.
        Used by ``portlet_prefs`` to construct the URL to
        ``@@overview-controlpanel``.
        """
        return getSite().absolute_url()
    def __call__(self, *args, **kwargs):
        """Handle possible submission"""

        if not self.request.get('form.submitted'):
            return self.index()

        context = aq_inner(self.context)
        action = self.request.get('form.action')

        id = self.request.get('id', '')

        if action in ('create', 'edit'):

            # Form variables
            title = self.request.get('title', '').strip()
            category = self.request.category
            strength = self.request.strength
            url = self.request.get('url', '').strip()
            connexions_id = self.request.get('connexions_id', '').strip()
            if action == 'create':
                urlorid = self.request.urlorid
                version = self.request.get('version', '').strip() or 'latest'
            if action == 'edit':
                urlorid = 'url'

            # Validate the form
            errors = {}

            if not title:
                errors['title'] = _("Please enter a title")

            if urlorid == 'url':
                if not url:
                    errors['url'] = _("Please enter an URL")
                else:
                    # Validate url
                    m = re.match(r'(%s)s?://[^\s\r\n]+' % '|'.join(protocols),
                                 url)
                    if m is None:
                        errors['url'] = _("Please enter a valid URL")
                target = url

            elif urlorid == 'id':
                if not connexions_id:
                    errors['connexions_id'] = _(
                        "Please enter an OpenStax CNX ID")
                else:
                    # Does target exist?
                    try:
                        target = context.content.getRhaptosObject(
                            connexions_id, version).url()
                    except KeyError:
                        errors['connexions_id'] = _(
                            "Please enter a valid OpenStax CNX ID and optional version"
                        )

            if errors:
                if action == 'create':
                    html = self.macroContent('@@%s/macros/newlink' %
                                             self.__name__,
                                             errors=errors)
                if action == 'edit':
                    html = self.macroContent('@@%s/macros/editlink' %
                                             self.__name__,
                                             errors=errors,
                                             **self.request.form)
                return html

        # Generate the response HTML snippet (new strength icon, title, link)
        if action == 'edit':
            # Construct a temporary ExtendedLink so the macro can be rendered
            link = ExtendedLink('dummy', context.absolute_url(), target,
                                category, int(strength), title)
            html = self.macroContent('@@%s/macros/editlink_label' %
                                     self.__name__,
                                     link=link)

        # Change the data on the server
        title = self.request.title.strip()
        category = self.request.category
        strength = self.request.strength
        url = self.request.url.strip()

        if action == 'remove':
            html = ''
            context.manage_delObjects([id])

        elif action == 'create':
            link = context.addLink(url, title, category, int(strength))
            html = self.macroContent('@@%s/macros/editlink_row' %
                                     self.__name__,
                                     link=link,
                                     target=target,
                                     marker_class='create')

        elif action == 'edit':
            link = context._getOb(id)
            link.edit(context.absolute_url(),
                      target=url,
                      title=title,
                      category=category,
                      strength=int(strength))

        return 'close:' + html
Beispiel #51
0
    def workflowHistory(self, complete=True):
        """Return workflow history of this context, for all workflows in its
        chain.

        Taken from plone_scripts/getWorkflowHistory.py
        """
        context = aq_inner(self.context)
        # Since switching to DCWorkflow's getInfoFor, we rely on its
        # permission checks.
        #if not (_checkPermission('Request review', context) or
        #    _checkPermission('Review portal content', context)):
        #    return []

        wf_tool = getToolByName(context, 'portal_workflow')
        membership = getToolByName(context, 'portal_membership')
        workflows = wf_tool.getWorkflowsFor(self.context)

        review_history = []

        try:
            # get total history
            for wf in workflows:
                wf_review_history = wf.getInfoFor(context, 'review_history',
                                                  [])
                # Add in the state_var, to find the title and use in template
                for item in wf_review_history:
                    item['state_var'] = wf.state_var
                review_history.extend(wf_review_history)

            if not complete:
                # filter out automatic transitions.
                review_history = [r for r in review_history if r['action']]
            else:
                review_history = list(review_history)

            portal_type = context.portal_type
            anon = _(u'label_anonymous_user', default=u'Anonymous User')

            for r in review_history:
                r['type'] = 'workflow'
                r['transition_title'] = wf_tool.getTitleForTransitionOnType(
                    r['action'], portal_type) or _("Create")
                r['state_title'] = wf_tool.getTitleForStateOnType(
                    r[r['state_var']], portal_type)
                actorid = r['actor']
                r['actorid'] = actorid
                if actorid is None:
                    # action performed by an anonymous user
                    r['actor'] = {'username': anon, 'fullname': anon}
                    r['actor_home'] = ''
                else:
                    r['actor'] = membership.getMemberInfo(actorid)
                    if r['actor'] is not None:
                        r['actor_home'] = self.navigation_root_url + '/author/' + actorid
                    else:
                        # member info is not available
                        # the user was probably deleted
                        r['actor_home'] = ''
            review_history.reverse()

        except WorkflowException:
            log('plone.app.layout.viewlets.content: '
                '%s has no associated workflow' % context.absolute_url(),
                severity=logging.DEBUG)

        return review_history
class ISiteSyndicationSettings(Interface):

    allowed = schema.Bool(title=_(u'Allowed'),
                          description=_(
                              u'Allow syndication for collections and folders '
                              u'on site.'),
                          default=True)

    default_enabled = schema.Bool(
        title=_(u'Enabled by default'),
        description=_(u'If syndication should be enabled by default for all '
                      u'folders and collections.'),
        default=False)

    search_rss_enabled = schema.Bool(
        title=_(u'Search RSS enabled'),
        description=_(u'Allows users to subscribe to feeds of search results'),
        default=True)

    show_author_info = schema.Bool(
        title=_(u'Show author info'),
        description=_(u'Should feeds include author information'),
        default=True)

    max_items = schema.Int(
        title=_(u'label_syndication_max_items', default=u'Maximum items'),
        description=_(
            u'help_syndication_max_items',
            default=u'Maximum number of items that will be syndicated.'),
        default=15)

    allowed_feed_types = schema.Tuple(
        title=_(u'Allowed Feed Types'),
        description=_(u"Separate view name and title by '|'"),
        required=True,
        missing_value=None,
        default=("RSS|RSS 1.0", "rss.xml|RSS 2.0", "atom.xml|Atom",
                 "itunes.xml|iTunes"),
        value_type=schema.TextLine())

    site_rss_items = schema.Tuple(
        title=_(u'Site RSS'),
        description=_(u'Paths to folders and collections to link to '
                      u'at the portal root.'),
        required=False,
        default=('/news/aggregator', ),
        value_type=schema.Choice(
            vocabulary="plone.app.vocabularies.SyndicatableFeedItems"))

    show_syndication_button = schema.Bool(
        title=_(u"Show settings button"),
        description=_(u"Makes it possible to customize syndication settings "
                      u"for particular folders and collections "))

    show_syndication_link = schema.Bool(
        title=_(u"Show feed link"),
        description=_(u"Enable RSS link document action on the syndication "
                      u"content item."))
Beispiel #53
0
class MailControlPanelForm(controlpanel.RegistryEditForm):

    id = "MailControlPanel"
    label = _(u"Mail Settings")
    schema = IMailSchema
    schema_prefix = "plone"

    @button.buttonAndHandler(_('Save'), name=None)
    def handleSave(self, action):
        self.save()

    @button.buttonAndHandler(_('Cancel'), name='cancel')
    def handleCancel(self, action):
        super(MailControlPanelForm, self).handleCancel(self, action)

    def save(self):
        data, errors = self.extractData()
        if errors:
            self.status = self.formErrorsMessage
            return False
        #keep password field
        if (data.get('smtp_userid') is not None
                and data.get('smtp_pass') is None):
            del data['smtp_pass']
        self.applyChanges(data)
        return True

    @button.buttonAndHandler(_('label_smtp_test',
                               default='Save and send test e-mail'),
                             name='test')
    def handle_test_action(self, action):
        # Save data first
        if not self.save():
            return
        mailhost = getToolByName(self.context, 'MailHost')

        registry = getUtility(IRegistry)
        mail_settings = registry.forInterface(IMailSchema, prefix='plone')
        fromaddr = mail_settings.email_from_address
        fromname = mail_settings.email_from_name

        message = ("Hi,\n\nThis is a test message sent from the Plone "
                   "'Mail settings' control panel. Your receipt of this "
                   "message (at the address specified in the Site 'From' "
                   "address field) indicates that your e-mail server is "
                   "working!\n\n"
                   "Have a nice day.\n\n"
                   "Love,\n\nPlone")
        email_charset = mail_settings.email_charset
        subject = "Test e-mail from Plone"

        # Make the timeout incredibly short. This is enough time for most mail
        # servers, wherever they may be in the world, to respond to the
        # connection request. Make sure we save the current value
        # and restore it afterward.
        timeout = socket.getdefaulttimeout()
        try:
            socket.setdefaulttimeout(3)
            try:
                mailhost.send(message,
                              mto=fromaddr,
                              mfrom=fromaddr,
                              subject=subject,
                              charset=email_charset,
                              immediate=True)

            except (socket.error, MailHostError, smtplib.SMTPException):
                # Connection refused or timeout.
                log.exception('Unable to send test e-mail.')
                value = sys.exc_info()[1]
                msg = _(u'Unable to send test e-mail ${error}.',
                        mapping={'error': unicode(value)})
                IStatusMessage(self.request).addStatusMessage(msg,
                                                              type='error')
            else:
                IStatusMessage(self.request).addStatusMessage(
                    _(u'Success! Check your mailbox for the test message.'),
                    type='info')
        finally:
            # Restore timeout to default value
            socket.setdefaulttimeout(timeout)
Beispiel #54
0
class IExpiryPortlet(IPortletDataProvider):
    count = schema.Int(title=_(u'Number of items to display'),
                       description=_(u'How many items to list.'),
                       required=True,
                       default=5)
Beispiel #55
0
 def title(self):
     return _(u"Search")
class IBundleRegistry(zope.interface.Interface):

    jscompilation = schema.ASCIILine(
        title=_(u"URL of the last js compilation"),
        required=False)

    csscompilation = schema.ASCIILine(
        title=_(u"URL of the last css compilation"),
        required=False)

    last_compilation = schema.Datetime(
        title=_(u"Last compiled date"),
        description=_(u"Date time of the last compilation of this bundle"),
        required=False)

    expression = schema.ASCIILine(
        title=_(u"Expression to render"),
        description=_(u"In case its a bundle we can have a condition to render it"),
        required=False)

    conditionalcomment = schema.ASCIILine(
        title=_(u"Conditional comment"),
        description=_(u"In case you want to render this resource on conditional comment"),
        required=False)

    resources = schema.List(
        title=_(u"Loaded resources"),
        description=_(u"The resources that is going to be loaded on this bundle in order"),
        value_type=schema.ASCIILine(title=_(u"Resource name")),
        required=False)

    enabled = schema.Bool(
        title=_(u"It's enabled?"),
        default=True,
        required=False)

    compile = schema.Bool(
        title=_(u"Does your bundle contains any RequireJS or LESS file?"),
        description=_(u"If its true and you modify this bundle you need to build it before production"),
        default=True,
        required=False)

    depends = schema.ASCIILine(
        title=_(u"Depends on another bundle"),
        description=_(u"In case you want to be the last: *, in case its the first should be empty"),
        required=False)
Beispiel #57
0
    """
    pass


class NotEditableFieldFactory(FieldFactory):
    implements(IFieldFactory)

    title = _(u'(protected)')

    def protected(self, field):
        return True


FullnameFieldFactory = NotEditableFieldFactory(
    ProtectedTextLine,
    _(u'label_full_name', default=u'Full Name'),
)

EmailFieldFactory = NotEditableFieldFactory(
    ProtectedTextLine,
    _(u'label_email', default=u'E-mail'),
)


class IUserDataSchema(Interface):
    """
    """

    fullname = ProtectedTextLine(
        title=_(u'label_full_name', default=u'Full Name'),
        description=_(u'help_full_name_creation',
Beispiel #58
0
class EditForm(base.EditForm):
    form_fields = form.Fields(ISearchPortlet)
    label = _(u"Edit Search Portlet")
    description = _(u"This portlet shows a search box.")
Beispiel #59
0
class BaseVocabularyView(BrowserView):
    def __call__(self):
        """
        Accepts GET parameters of:
        name: Name of the vocabulary
        field: Name of the field the vocabulary is being retrieved for
        query: string or json object of criteria and options.
            json value consists of a structure:
                {
                    criteria: object,
                    sort_on: index,
                    sort_order: (asc|reversed)
                }
        attributes: comma seperated, or json object list
        batch: {
            page: 1-based page of results,
            size: size of paged results
        }
        """
        context = self.get_context()
        self.request.response.setHeader("Content-type", "application/json")

        try:
            vocabulary = self.get_vocabulary()
        except VocabLookupException, e:
            return json_dumps({'error': e.message})

        results_are_brains = False
        if hasattr(vocabulary, 'search_catalog'):
            query = self.parsed_query()
            results = vocabulary.search_catalog(query)
            results_are_brains = True
        elif hasattr(vocabulary, 'search'):
            try:
                query = self.parsed_query()['SearchableText']['query']
            except KeyError:
                results = iter(vocabulary)
            else:
                results = vocabulary.search(query)
        else:
            results = vocabulary

        try:
            total = len(results)
        except TypeError:
            # do not error if object does not support __len__
            # we'll check again later if we can figure some size
            # out
            total = 0

        # get batch
        batch = _parseJSON(self.request.get('batch', ''))
        if batch and ('size' not in batch or 'page' not in batch):
            batch = None  # batching not providing correct options
        if batch:
            # must be slicable for batching support
            page = int(batch['page'])
            size = int(batch['size'])
            if size > MAX_BATCH_SIZE:
                raise Exception('Max batch size is 500')
            # page is being passed in is 1-based
            start = (max(page - 1, 0)) * size
            end = start + size
            # Try __getitem__-based slice, then iterator slice.
            # The iterator slice has to consume the iterator through
            # to the desired slice, but that shouldn't be the end
            # of the world because at some point the user will hopefully
            # give up scrolling and search instead.
            try:
                results = results[start:end]
            except TypeError:
                results = itertools.islice(results, start, end)

        # build result items
        items = []

        attributes = _parseJSON(self.request.get('attributes', ''))
        if isinstance(attributes, basestring) and attributes:
            attributes = attributes.split(',')

        translate_ignored = [
            'Creator',
            'Date',
            'Description',
            'Title',
            'author_name',
            'cmf_uid',
            'commentators',
            'created',
            'effective',
            'end',
            'expires',
            'getIcon',
            'getId',
            'getRemoteUrl',
            'in_response_to',
            'listCreators',
            'location',
            'modified',
            'start',
            'sync_uid',
            'path',
            'getURL',
            'EffectiveDate',
            'getObjSize',
            'id',
            'UID',
            'ExpirationDate',
            'ModificationDate',
            'CreationDate',
        ]
        if attributes:
            base_path = getNavigationRoot(context)
            for vocab_item in results:
                if not results_are_brains:
                    vocab_item = vocab_item.value
                item = {}
                for attr in attributes:
                    key = attr
                    if ':' in attr:
                        key, attr = attr.split(':', 1)
                    if attr in _unsafe_metadata:
                        continue
                    if key == 'path':
                        attr = 'getPath'
                    val = getattr(vocab_item, attr, None)
                    if callable(val):
                        if attr in _safe_callable_metadata:
                            val = val()
                        else:
                            continue
                    if key == 'path':
                        val = val[len(base_path):]
                    if key not in translate_ignored and isinstance(
                            val, basestring):
                        item[key] = translate(_(safe_unicode(val)),
                                              context=self.request)
                    else:
                        item[key] = val
                items.append(item)
        else:
            for item in results:
                items.append({'id': item.value, 'text': item.title})

        if total == 0:
            total = len(items)

        return json_dumps({'results': items, 'total': total})
Beispiel #60
0
class PropertiesActionView(ContentsBaseAction):
    success_msg = _('Successfully updated metadata')
    failure_msg = _('Failure updating metadata')
    required_obj_permission = 'Modify portal content'

    def __call__(self):

        if self.request.form.get('render') == 'yes':
            lang_factory = getUtility(
                IVocabularyFactory,
                'plone.app.vocabularies.SupportedContentLanguages')
            lang_vocabulary = lang_factory(self.context)
            languages = [{
                'title': term.title,
                'value': term.value
            } for term in lang_vocabulary]
            return self.json({
                'languages': [{
                    'title':
                    translate(
                        _('label_no_change', default='No change'),
                        context=self.request,
                    ),
                    'value':
                    ''
                }] + languages
            })

        self.putils = getToolByName(self.context, 'plone_utils')
        self.effectiveDate = self.request.form.get('effectiveDate')
        self.expirationDate = self.request.form.get('expirationDate')
        self.copyright = self.request.form.get('copyright')
        self.contributors = self.request.form.get('contributors')
        if self.contributors:
            self.contributors = self.contributors.split(',')
        else:
            self.contributors = []
        self.creators = self.request.form.get('creators', '')
        if self.creators:
            self.creators = self.creators.split(',')
        self.exclude = self.request.form.get('exclude-from-nav')
        self.language = self.request.form.get('language')
        self.recurse = self.request.form.get('recurse', 'no') == 'yes'
        return super().__call__()

    def dx_action(self, obj):
        if self.effectiveDate and hasattr(obj, 'effective_date'):
            obj.effective_date = DateTime(self.effectiveDate)
        if self.expirationDate and hasattr(obj, 'expiration_date'):
            obj.expiration_date = DateTime(self.expirationDate)
        if self.copyright and hasattr(obj, 'rights'):
            obj.rights = self.copyright
        if self.contributors and hasattr(obj, 'contributors'):
            obj.contributors = tuple(self.contributors)
        if self.creators and hasattr(obj, 'creators'):
            obj.creators = tuple(self.creators)
        if self.exclude and hasattr(obj, 'exclude_from_nav'):
            obj.exclude_from_nav = self.exclude == 'yes'

        behavior_categorization = ICategorization(obj)
        if self.language and behavior_categorization:
            behavior_categorization.language = self.language

    def at_action(self, obj):
        if self.effectiveDate:
            try:
                obj.setEffectiveDate(DateTime(self.effectiveDate))
            except AttributeError:
                pass
        if self.expirationDate:
            try:
                obj.setExpirationDate(DateTime(self.expirationDate))
            except AttributeError:
                pass
        if self.copyright:
            try:
                obj.setRights(self.copyright)
            except AttributeError:
                pass
        if self.contributors:
            try:
                obj.setContributors(self.contributors)
            except AttributeError:
                pass
        if self.creators:
            try:
                obj.setCreators(self.creators)
            except AttributeError:
                pass
        if self.exclude:
            try:
                obj.setExcludeFromNav(self.exclude == 'yes')
            except AttributeError:
                pass
        if self.language:
            try:
                obj.setLanguage(self.language)
            except AttributeError:
                pass

    def action(self, obj, bypass_recurse=False):

        if self.putils.isDefaultPage(obj):
            self.action(obj.aq_parent, bypass_recurse=True)
        recurse = self.recurse and not bypass_recurse
        if recurse and IFolderish.providedBy(obj):
            for sub in obj.values():
                self.action(sub)

        if IDexterityContent.providedBy(obj):
            self.dx_action(obj)
        else:
            self.at_action(obj)

        obj.reindexObject()