Exemplo n.º 1
0
    def block_portlets(self, action):
        status = IStatusMessage(self.request)
        context = Acquisition.aq_inner(self.context)
        data, error = self.extractData()
        portlet_manager = data.get('portlet_manager', None)
        blockstatus = data.get('blockstatus', False)

        manager = data.get('portlet_manager', None)
        path = "/".join(context.getPhysicalPath())

        if manager is not None:
            managernames = [manager]
        else:
            managernames = utils.get_portlet_manager_names()

        status.addStatusMessage(u'Set portlet block status on %s' % ', '.join(
            managernames), type='info')
        managers = dict()
        for managername in managernames:
            managers[managername] = assignment_mapping_from_key(
                                            context,
                                            managername,
                                            CONTEXT_CATEGORY,
                                            path,
                                            )

        info, warnings, errors = utils.exec_for_all_langs(
                                                    context,
                                                    utils.block_portlets,
                                                    managers=managers,
                                                    blockstatus=blockstatus,
                                                    )

        self.handle_status(status, info, warnings, errors)
    def __call__(self):
        """
        """
        request = aq_inner(self.request)
        form = request.form

        if not 'form.button.Delete' in form:
            return super(PatchedManageAssignments, self).__call__()

        context = aq_inner(self.context)
        assignable = IRuleAssignmentManager(context)
        storage = getUtility(IRuleStorage)
        status = IStatusMessage(self.request)
        rule_ids = form.get('rule_ids', ())
        path = '/'.join(context.getPhysicalPath())

        for r in rule_ids:
            del assignable[r]
            assignments = get_assignments(storage[r])
            if path in assignments:
                msg = 'Try to remove from %r' % (
                    assignments
                )
                logger.info(msg)
                try:
                    assignments.remove(path, None)
                except:
                    assignments.remove(path)
        status.addStatusMessage(_(u"Assignments deleted."), type='info')
        return self.template()
Exemplo n.º 3
0
    def handle_save(self, action):
        data, errors = self.extractData()
        if errors:
            return

        props = dict(
            title=data['title'],
            description=data.get('description', ''),
            remoteUrl=data['remoteUrl'],
            fileCategories=tuple(
                tuple(x.values())
                for x in data['fileCategories']
            )
        )

        lfa = LandFileApi(self.context.landfiles)
        try:
            landfile = lfa.add_with_filesize(**props)
        except (KeyError, OSError) as err:
            raise ActionExecutionError(Invalid(err.message))

        messages = IStatusMessage(self.request)
        messages.add(u'Added landfile: {}'.format(landfile.title))

        self.redirect_to_listing()
 def __call__(self):
     manager = self.context.restrictedTraverse(VIEW_NAME)
     if manager.isin():
         manager.rm()
         status = IStatusMessage(self.request)
         status.add(_(u"Removed from favorite"))
     self.request.response.redirect(self.nextURL())
Exemplo n.º 5
0
    def __call__(self):
        context = aq_inner(self.context)
        request = self.request
        response_id = self.validate_response_id()
        file = None
        if response_id != -1:
            response = self.folder[response_id]
            file = response.attachment
            if file is None:
                status = IStatusMessage(request)
                msg = _(u"Response id ${response_id} has no attachment.",
                        mapping=dict(response_id=response_id))
                msg = translate(msg, 'Poi', context=context)
                status.addStatusMessage(msg, type='error')
        if file is None:
            request.response.redirect(context.absolute_url())

        # From now on file exists.
        # Code mostly taken from Archetypes/Field.py:FileField.download
        filename = getattr(file, 'filename', file.getId())
        if filename is not None:
            if FILE_NORMALIZER:
                filename = IUserPreferredFileNameNormalizer(request).normalize(
                    safe_unicode(filename, context.getCharset()))
            else:
                filename = safe_unicode(filename, context.getCharset())
            header_value = contentDispositionHeader(
                disposition='attachment',
                filename=filename)
            request.response.setHeader("Content-disposition", header_value)
        return file.index_html(request, request.response)
Exemplo n.º 6
0
 def send_unsubscribe_email(self, subscriber):
     newsletter = self.context
     catalog = getToolByName(self.context, "portal_catalog")
     query = {}
     query["portal_type"] = "ENLSubscriber"
     query["email"] = subscriber
     results = catalog.unrestrictedSearchResults(query)
     messages = IStatusMessage(self.request)
     if results:
         subscriber_brain = results[0]
         unsubscribe_url = self.newsletter_url +\
             '/unsubscribe?subscriber=' + subscriber_brain.UID
         msg_text = """%s: %s""" % (
             newsletter.getUnsubscribe_string(), unsubscribe_url)
         api.portal.send_email(
             recipient=subscriber,
             sender=self.context.email_from_address,
             subject=_(u"confirm newsletter unsubscription"),
             body=msg_text,
         )
         messages.addStatusMessage(
             _("We send you an email, please confirm this unsubscription."),
             "info")
     else:
         # todo: write an extra error msg if a plone user wants to
         # unsubscribe himself
         messages.addStatusMessage(
             _("Your email address could not be found in subscribers."),
             "error")
Exemplo n.º 7
0
    def sendMail(
        self,
        msg,
        mail_from,
        mail_to,
        subject,
        ):

        if mail_to:
            bcc_to = []
            if NOTIFICATION_LOG_ADDR:
                msg = u'''From: %s
To: %s
Bcc: %s
Subject: %s

''' \
                    % (mail_from, mail_to, NOTIFICATION_LOG_ADDR,
                       subject) + msg
                bcc_to = bcc_to + [NOTIFICATION_LOG_ADDR]
            if not isinstance(mail_to, list):
                mail_to = [mail_to]
            self.mailhost.send(messageText=msg, mto=mail_to + bcc_to,
                               mfrom=mail_from, subject=subject,
                               charset='utf-8')
        else:
            (mail_to, pref_lang) = self.findRecipient()
            messages = IStatusMessage(self.request)
            messages.addStatusMessage(self.ts.translate(_('mail_no_recipients'
                    ), target_language=pref_lang), type='warning')
Exemplo n.º 8
0
    def handleApply(self, action):
        data, errors = self.extractData()
        messages = IStatusMessage(self.request)
        if errors:
            return False
        try:
            source = "*****@*****.**"
            recipients = [recipients_voc.getTerm(data["recipient"]).value, ]
            subject = "[Sito Viola] Nuova mail da %(name)s" % data

            # Custom message with a name filled in
            message = u"""Hai ricevuto una mail di contatto dal sito violareggiocalabria.it:

            Dati del richiedente:
            Nome: %(name)s
            Email: %(email)s
            Telefono: %(phone)s
            Testo:

            %(text)s

            """ % (data)
            encoding = 'utf-8'
            message = MIMEText(message, 'plain', encoding)
            message['Reply-To'] = Header(data.get("email", source), encoding)
            send_mail(source, recipients, subject, message)
            messages.add(u"""La tua email è stata inviata con successo.
                         Ti risponderemo prima possibile.""",
                         type=u"info")
        except:
            messages.add(u"""C'è stato un problema nell'invio della posta.
                         Riprova o contattaci telefonicamente.""",
                         type=u"error")
            return False
Exemplo n.º 9
0
    def handle_migrate(self, action):
        data, errors = self.extractData()

        if errors:
            return

        changed_base_classes = data.get('changed_base_classes', [])
        if not changed_base_classes:
            return

        migrate_to_folderish = data.get('changed_base_classes', False)
        catalog = getToolByName(self.context, "portal_catalog")
        migrated = []
        not_migrated = []
        for brain in catalog():
            obj = brain.getObject()
            old_class_name = dxmigration.get_old_class_name_string(obj)
            if old_class_name in changed_base_classes:
                if dxmigration.migrate_base_class_to_new_class(
                        obj, migrate_to_folderish=migrate_to_folderish):
                    migrated.append(obj)
                else:
                    not_migrated.append(obj)

        messages = IStatusMessage(self.request)
        info_message_template = 'There are {0} objects migrated.'
        warn_message_template = 'There are not {0} objects migrated.'
        if migrated:
            msg = info_message_template.format(len(migrated))
            messages.addStatusMessage(msg, type='info')
        if not_migrated:
            msg = warn_message_template.format(len(not_migrated))
            messages.addStatusMessage(msg, type='warn')
        self.request.response.redirect(self.request['ACTUAL_URL'])
 def update(self):
     super(FoundationDashboard, self).update()
     if self.empty() and self.can_edit():
         status = IStatusMessage(self.request)
         msg = _p(u"info_empty_dashboard")
         msg = translate(msg, domain='plone', context=self.request)
         status.add(msg, "info")
def plonegroup_contact_transition(contact, event):
    """
        React when a IPloneGroupContact transition is done
    """
    if event.transition and event.transition.id == 'deactivate':
        # check if the transition is selected
        registry = getUtility(IRegistry)
        pp = api.portal.get_tool('portal_properties')
        errors = []
        if contact.UID() in registry[ORGANIZATIONS_REGISTRY]:
            errors.append(_('This contact is selected in configuration'))
        elif pp.site_properties.enable_link_integrity_checks:
            search_value_in_objects(contact, contact.UID(), p_types=[], type_fields={})
            storage = ILinkIntegrityInfo(contact.REQUEST)
            breaches = storage.getIntegrityBreaches()
            if contact in breaches:
                errors.append(_("This contact is used in following content: ${items}",
                                mapping={'items': ', '.join(['<a href="%s" target="_blank">%s</a>'
                                                             % (i.absolute_url(), i.Title())
                                                             for i in breaches[contact]])}))
        if errors:
            smi = IStatusMessage(contact.REQUEST)
            smi.addStatusMessage(_('You cannot deactivate this item !'), type='error')
            smi.addStatusMessage(errors[0], type='error')
            view_url = getMultiAdapter((contact, contact.REQUEST), name=u'plone_context_state').view_url()
            # contact.REQUEST['RESPONSE'].redirect(view_url)
            raise Redirect(view_url)
 def __call__(self):
     # check that we can actually access this form,
     # aka the current user has an advice to add or edit
     form = self.request.form
     cancelled = form.get('form.button.Cancel', False)
     submitted = form.get('form.button.Migrate', False)
     # test = form.get('form.button.Test', False)
     if submitted:
         # proceed, call the migration methdd
         results = self.migrate()
         messages = IStatusMessage(self.request)
         for migration_result in results:
             res_type = migration_result.get('type')
             res_infos = migration_result.get('infos')
             if res_infos.get('errors'):
                 messages.add(
                     u'Error when migrating "%s" type. Check the '
                     u'log for other informations.'
                     % res_type, type=u"error")
             else:
                 msg = translate(
                     'Migration applied succesfully for %s "%s" items.'
                     % (res_infos.get('counter'), res_type),
                     domain='plone.app.contenttypes')
                 messages.add(msg, type=u"info")
     elif cancelled:
         self.request.response.redirect(form.get('form.HTTP_REFERER'))
     return self.index()
Exemplo n.º 13
0
    def _on_save(self, data):
        """
        Deleting the gray-scale converted resources
        from the filesystem cache
        """
        messages = IStatusMessage(self.request)
        if data.get("delete_cached_resources"):
            site = getSite()
            try:
                path = str("/++%s++%s" % (TYPE, THEME))
                location = site.restrictedTraverse(path).directory
            except AttributeError, e:
                log.info("Unable to remove files for: %s due to error: %s" % (path, e))
                message = _(u"Couldn't remove files from %s" % path)
                messages.addStatusMessage(message, type="error")
                return

            try:
                log.info("Removing cached gray-scale files from: %s" % location)
                for filename in os.listdir(location):
                    file_path = os.path.join(location, filename)
                    if os.path.isfile(file_path):
                        os.unlink(file_path)
                    else:
                        shutil.rmtree(file_path)
            except OSError, e:
                log.info("Unable to remove files from: %s, error: %s" % (location, e))
                message = _(u"Couldn't remove files from %s" % location)
                messages.addStatusMessage(message, type="error")
Exemplo n.º 14
0
    def render(self, *a, **kw):
        errors = []
        results = ''
        status = IStatusMessage(self.request)
        data = self.request['_data']
        
        # In the future we might implement other ways to render file
        # information, either for other types of backends or even file
        # formats (which file renderer should take over, but...), so
        # this serves as a placeholder of sort.
        view = 'fileinfo'
        fileview = zope.component.getMultiAdapter(
            (self.context, self.request), name=view)
        try:
            # XXX current way to disable main_template
            results = fileview.call_template()
        except:
            errors.append('failed to render file information')

        if errors:
            # probably should only show this info message to users who
            # can deal with this.
            status.addStatusMessage(' '.join(errors), 'info')

        if results:
            return results
Exemplo n.º 15
0
    def set_blacklist_status(self, manager, group_status, content_type_status,
                             context_status):
        """Stay on the same page rather then redirecting to the portlet
        management view.
        """
        superclass = super(CustomManageContextualPortlets, self)
        superclass.set_blacklist_status(
            manager, group_status, content_type_status, context_status
        )

        # Give some feedback to the user, otherwise he might miss the fact
        # that the form has been submitted.
        messages = IStatusMessage(self.request)
        messages.add(text=_(u'Settings have been saved.'), type=u'success')

        base_url = str(
            getMultiAdapter((self.context, self.request), name='absolute_url')
        )

        if self.request.get('HTTP_REFERER', '').endswith('manage-footer'):
            # This is the part we need to override from the parent class.
            self.request.response.redirect(base_url + '/manage-footer')
        else:
            self.request.response.redirect(base_url + '/@@manage-portlets')

        return ''
    def handleCancel(self, action):

        messages = IStatusMessage(self.request)
        messages.add(_(u"Review submission canceled"), type=u"info")

        redirect = self.request.response.redirect
        redirect(self.context.absolute_url())
Exemplo n.º 17
0
    def handle_buscar(self, action, data):
        db = getUtility(IDatabase, name=DB_NAME)
        mapper_class = db.mappers['posto'].class_
        query = db.session.query(mapper_class)
        ativo = data.get('ativo')
        query = query.filter(mapper_class.ativo == ativo)
	#only add these items in a query if value is True
	for item in ['ferramentas','eletroportateis','eletronicos','bebedouros']:
	    value = data.get(item, False)
	    if value:
		query = query.filter(getattr(mapper_class, item) == value)
        modificado = data.get('modificado')
	criacao = data.get('criacao')
        if modificado is not None:
            query = query.filter(mapper_class.modificado >= modificado)
	if criacao is not None:
            query = query.filter(mapper_class.criacao >= criacao)
        for field in ['cod','cidade','bairro','uf']:
            if data.get(field) is not None:
                value = data.get(field)
                query = query.filter("%s ~* '%s'" % (field, value))

        count = query.count()
        self.results = query.all()
        if not self.results:
            msg = "Nenhum registro foi encontrado."
        else:
            msg = "%d registro(s)." % count
        status = IStatusMessage(self.request)
        status.addStatusMessage(msg, u'info')
Exemplo n.º 18
0
    def __call__(self, request):
        value = request.form.get(self.field_name, request.get(self.field_name, None))

        if value is not None:
            messages = IStatusMessage(request)
            catalog = getToolByName(self.context, "portal_catalog")
            plone_utils = getToolByName(self.context, 'plone_utils', None)

            parent = aq_parent(aq_inner(self.context))

            # Get the object metatype that we are going to create
            object_type = self.context.Type()

            # Actual folder where the object is going to be created, ignoring the portal_factory check
            object_folder = str('/'.join(parent.getPhysicalPath()))
            object_folder = object_folder.replace('/portal_factory/'+object_type,'')

            results = self.context.portal_catalog.searchResults(portal_type=object_type,
                                                                path={'query':object_folder,'level':0,'depth':1},
                                                                Title=value)

            for result in results:
                if self.context.UID() == result.getObject().UID():
                    return None

            if results:
                messages.addStatusMessage(_(u'There is an object in this folder with the same type and title'), type="error")
                return { self.field_name: '' }

        # Returning None means no error
        return None
Exemplo n.º 19
0
    def update(self):
        form = LoadFromSimilarForBookForm(self.context, self.request)
        view = LoadFromSimilarForBookSubView(self.context, self.request)
        view = view.__of__(self.context)
        view.form_instance = form
        self.loadsimilarform = view
        form.parent_form = self
        hiddenFields = ['related_aleph_record',
                        'summary_aleph_record',
                        'isClosed',
                        'thumbnail',
                        'shouldBeFullyCatalogized',
                        'isWellFormedForLTP',
                        'voucher']
        
        for field in hiddenFields:
            if field in self.fields:
                del self.fields[field]

        super(AddAtOnceForm,self).update()
        sdm = self.context.session_data_manager
        session = sdm.getSessionData(create=True)
        proper_record = session.get('proper_record',None)
        # proper_record = getAlephRecord()
        if proper_record:
            messages = IStatusMessage(self.request)
            messages.addStatusMessage(u"Formulář je předvyplněn vybraným záznamem z Alephu.", type="info")
            self.loadValuesFromAlephRecord(proper_record)
            session.set('proper_record',None)
Exemplo n.º 20
0
    def handleApply(self, action):
        data, errors = self.extractData()

        # get write access to the database
        portal_state = getMultiAdapter(
            (self.context, self.request),
            name=u'plone_portal_state'
            )
        navigation_root = portal_state.navigation_root()
        writer = IEventDatabaseWriteProvider(navigation_root)

        if errors:
            self.status = self.formErrorsMessage
            return

        for key in EventOrgEditForm.context_attributes:
            value = data.get(key)
            setattr(self.context, key, value)

        org_data = {}
        for key in EventOrgEditForm.database_attributes:
            org_data[key] = data.get(key)
        if writer.db_org_id == 0:
            db_org_id = writer.insertOrg(**org_data)
            setattr(navigation_root, 'dbOrgId', db_org_id)
        else:
            writer.updateOrgData(**org_data)

        writer.updateOrgCats(data.get('org_categories', []))

        messages = IStatusMessage(self.request)
        messages.add(u"Organization event settings updated", type=u"info")

        self.request.response.redirect("caledit")
Exemplo n.º 21
0
    def handleBuild(self, action):
        """\
        Build the thing
        """

        # validate all groups.
        errors = extractError(self)
        if errors:
            self.status = _(u"Unable to build exposure due to input error; "
                "please review the form and make the appropriate changes, "
                "update each subsection using the provided button, and try "
                "again.")
            return

        wh = zope.component.getAdapter(self.context, IExposureWizard)

        try:
            moldExposure(self.context, self.request, wh.structure)
        except ProcessingError, e:
            # XXX almost certainly a bad idea but this fixes
            # tracker item 3610.
            import transaction
            transaction.doom()
            self._doomed = True
            status = IStatusMessage(self.request)
            status.addStatusMessage(_(str(e)), 'error')
            # maybe the subscriber to this can do the rollback?
            raise ActionExecutionError(e)
Exemplo n.º 22
0
    def update(self):
        if self.portal_state is None:
            self.portal_state = component.getMultiAdapter(
                (self.context, self.request), name=u'plone_portal_state'
            )

        if self.portal_registry is None:
            self.portal_registry = component.getUtility(IRegistry)

        if self.embed_settings is None:
            self.embed_settings = {}
            registry = self.portal_registry
            self.embed_settings = registry.forInterface(EtherpadEmbedSettings)

        if self.etherpad_settings is None:
            registry = self.portal_registry
            self.etherpad_settings = registry.forInterface(EtherpadSettings)

        if self.etherpad is None:
            self.etherpad = HTTPAPI(self.context, self.request)
            self.etherpad.update()
            try:
                self.etherpad.checkToken()
            except ValueError:
                status = IStatusMessage(self.request)
                msg = _(u"Etherpad connection error")
                status.add(msg)
                self.etherpad_iframe_url = ""
                return
        self._updateName()
        self._updateAuthor()
        self._updateId()
        self._updateSession()
        self._updateIframe()
Exemplo n.º 23
0
    def __call__(self):
        # Add a status message, showing whether the login has
        # succeeded or not.
        status = IStatusMessage(self.request)
        pps = getMultiAdapter((self.context, self.request),
                              name='plone_portal_state')
        anonymous = pps.anonymous()
        if anonymous and not self.show_group_options():
            success = False
            msg = PMF(u"Login failed")
            msg = translate(msg, 'plone', context=self.request)
            status.addStatusMessage(msg, type='error')
        elif anonymous:
            success = False
        else:
            success = True
            msg = PMF(u"heading_you_are_now_logged_in",
                      default=u"You are now logged in")
            msg = translate(msg, 'plone', context=self.request)
            status.addStatusMessage(msg, type='info')

        if anonymous and self.request.cookies.get('aselectattributes'):
            success = False
            logger.debug("We have an A-Select cookie but are still anonymous.")
        if (not success) or self.request.get('noredirect'):
            # Show the template.  Manually adding '?noredirect=1' to
            # the url may be handy for debugging: this way you stay on
            # this url, which means you can inspect the cookies.
            return self._template()

        logger.debug('Redirecting to Plone Site root.')
        # We are only defined on the Plone Site root, so we can just
        # redirect to the context.
        self.request.RESPONSE.redirect(self.context.absolute_url())
Exemplo n.º 24
0
 def add(self):
     request = self.request
     view = request.get('view', '')
     super(FavoriteActions, self).add()
     statusmsg = IStatusMessage(request)
     statusmsg.add(_("The item has been added to your favorites"))
     request.response.redirect(self.context.absolute_url() + '/' + view)
Exemplo n.º 25
0
 def __call__(self):
     self.update()
     message = _('Feed items updated')
     messages = IStatusMessage(self.request, alternate=None)
     if messages is not None:
         messages.addStatusMessage(message, 'info')
     self.request.response.redirect(self.context.absolute_url())
Exemplo n.º 26
0
 def setProperties(self):
     context = aq_inner(self.context)
     new = self.request.form.get('new_definition', None)
     columns = self.request.form.get('new_definition_columns', [])
     error = 0
     if new and new['name']:
         try:
             self._definitions.addDefinition(new['name'], new['style'], self._formatColumns(columns))
         except:
             transaction.abort()
             error = _(u'Unable to parse the columns field of the definition to be added')
     modify = self.request.form.get('definitions', [])[:]
     for definition in modify:
         if definition.has_key('delete'):
             self._definitions.removeDefinition(definition['id'])
         if definition.has_key('delete'):
             continue
         try:
             columns = self.request.form.get('definition_columns_%s' % definition['origname'], [])
             self._definitions.addDefinition(definition['name'], definition['style'], self._formatColumns(columns), definition['id'])
         except:
             transaction.abort()
             error = _(u'Unable to parse the columns field of one of the definitions to be modified')
     statusmessage = IStatusMessage(self.request)
     if error:
         statusmessage.addStatusMessage(error, 'error')
     else:
         statusmessage.addStatusMessage(_p(u'Changes saved.'), 'info')
Exemplo n.º 27
0
def forceUpdateProfile(principal, event):
    """ Redirect to edit profile if user has not completed info about
        thematic and institutional domains
    """
    site = getSite()
    if site is not None:
        membership = getToolByName(site, 'portal_membership')
        authenticated_user = membership.getAuthenticatedMember()
        t_d = authenticated_user.getProperty('thematic_domain', '')
        i_d = authenticated_user.getProperty('institutional_domain', '')

        if t_d == '' or i_d == '':
            request = getRequest()

            messages = IStatusMessage(request)
            messages.add(
                u"Please complete your profile adding your Professional " +
                "thematic domain and Institutional domain.", type=u"info")

            if request.get('came_from', None):
                request['came_from'] = ''
                request.form['came_from'] = ''
                request.form['next'] = ''

            edit_profile_url = site.portal_url() + '/@@personal-information'
            request.RESPONSE.redirect(edit_profile_url)
Exemplo n.º 28
0
    def update(self):
        context = aq_inner(self.context)
        self.helper = MultiLinguageContentListingHelper(context, self.request)

        if not self.helper.getSettings():
            messages = IStatusMessage(self.request)
            messages.addStatusMessage(u"Silvuple not configured in Site Setup", type="error")
Exemplo n.º 29
0
 def PurgeAction(self):
     """
     Purging actual object's cache by sending prepared request.
     The example request: 
     PURGE 5bf8c564b5da741f9bc9a14ca2509b94 HTTP/1.1
     Host: localhost:6081
     """
     mtool = getToolByName(self, 'portal_membership')
     host, port = self.getVarnishAddress()
     if not mtool.checkPermission("Modify portal content", self.context):
         raise Unauthorized
     
     purging_uids = [getUidOrId(self.context)]
     context_state = getMultiAdapter((self.context, self.request), name='plone_context_state')
     if context_state.is_default_page():
         purging_uids.append(getUidOrId(context_state.parent()))
     
     #TODO: Handle exceptions of connection problem
     for uid in purging_uids:
         connection = httplib.HTTPConnection(host, port)
         connection.putrequest('PURGE', uid)
         connection.putheader('Host', host + ':' + port)
         connection.endheaders()
         connection.send('')
         response = connection.getresponse()
     
     messages = IStatusMessage(self.request)
     messages.addStatusMessage(_("Cache of the page has been purged"), type="info")
     return self.request.RESPONSE.redirect(self.context.absolute_url())
Exemplo n.º 30
0
    def render(self):
        this_attendee = self.context
        trainings_uid = self.request.form.get('trainings_uid', [])
        if isinstance(trainings_uid, str):
            trainings_uid = [trainings_uid, ]
        seat_table = SeatTable(this_attendee)

        # confirmed trainings are always part of the selection
        all_trainings = list(this_attendee.confirmed_trainings())
        for uid in trainings_uid:
            if uid not in all_trainings:
                # was this training already ours
                # OR are there still available seats?
                if uid in this_attendee.trainings or seat_table.available_seats(uid):
                    all_trainings.append(uid)
                else:
                    training = uuidToObject(uid)
                    messages = IStatusMessage(self.request)
                    warning = _(u'This training is already fully booked') + ': ' + training.title
                    messages.addStatusMessage(warning, type="warning")
        # reserve a seat for each training
        seat_table.refresh_attendee_trainings(this_attendee, all_trainings)
        # store the list of trainings of this attendee
        this_attendee.trainings = all_trainings
        this_attendee.reindexObject(idxs=['trainings', ])
        # set the time of this operation for use in liberation of blocked seats
        this_attendee.last_time_trainings_were_set = datetime.now()
        if self.request.get('finish_button'):
            # back to the registration
            return self.request.response.redirect(this_attendee.getParentNode().absolute_url())
        else:
            return self.request.response.redirect(this_attendee.absolute_url())
Exemplo n.º 31
0
 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.')
     )
Exemplo n.º 32
0
class BaseRegistrationForm(AutoExtensibleForm, form.Form):
    """Form to be used as base for Register and Add User forms."""
    label = u""
    description = u""
    formErrorsMessage = _('There were errors.')
    ignoreContext = True
    enableCSRFProtection = True
    schema = ICombinedRegisterSchema

    # this attribute indicates if user was successfully registered
    _finishedRegister = False

    def __init__(self, *args, **kwargs):
        super(BaseRegistrationForm, self).__init__(*args, **kwargs)
        self.schema = getUtility(IRegisterSchemaProvider).getSchema()

    def _get_security_settings(self):
        """Return security settings from the registry."""
        registry = getUtility(IRegistry)
        return registry.forInterface(ISecuritySchema, prefix="plone")

    def render(self):
        if self._finishedRegister:
            return self.context.unrestrictedTraverse('registered')()

        return super(BaseRegistrationForm, self).render()

    def updateFields(self):
        """Fields are dynamic in this form, to be able to handle
        different join styles.
        """
        settings = self._get_security_settings()
        use_email_as_login = settings.use_email_as_login

        # Filter schema for registration
        omitted = []
        default_fields = IUserDataSchema.names() + IRegisterSchema.names()
        for name in self.schema:
            # we always preserve default fields
            if name in default_fields:
                omit = False
            else:
                forms_selection = getattr(self.schema[name], 'forms_selection',
                                          [])
                if u'On Registration' in forms_selection:
                    omit = False
                else:
                    omit = True
            omitted.append((Interface, name, omit))
        self.schema.setTaggedValue(OMITTED_KEY, omitted)

        # Finally, let autoform process the schema and any FormExtenders do
        # their thing
        super(BaseRegistrationForm, self).updateFields()

        if use_email_as_login:
            self.fields['email'].field.description = _(
                u'help_email_creation_for_login',
                default=u"Enter an email "
                "address. This will be your login name. We respect your "
                "privacy, and will not give the address away to any third "
                "parties or expose it anywhere.")
            del self.fields['username']
        else:
            self.fields['email'].field.description = _(
                u'help_email_creation',
                default=u"Enter an email address. This is necessary in case "
                u"the password is lost. We respect your privacy, and "
                u"will not give the address away to any third parties "
                u"or expose it anywhere.")

        # Change the password description based on PAS Plugin The user needs a
        # list of instructions on what kind of password is required.  We'll
        # reuse password errors as instructions e.g. "Must contain a letter and
        # a number".  Assume PASPlugin errors are already translated
        if self.fields.get('password', None):
            registration = getToolByName(self.context, 'portal_registration')
            err_str = registration.testPasswordValidity('')
            if err_str:
                msg = _(u'help_password_creation_with_errors',
                        default=u'Enter your new password. ${errors}',
                        mapping=dict(errors=err_str))
                self.fields['password'].field.description = msg

    def generate_user_id(self, data):
        """Generate a user id from data.

        We try a few options for coming up with a good user id:

        1. We query a utility, so integrators can register a hook to
           generate a user id using their own logic.

        2. If use_uuid_as_userid is set in the registry, we
           generate a uuid.

        3. If a username is given and we do not use email as login,
           then we simply return that username as the user id.

        4. We create a user id based on the full name, if that is
           passed.  This may result in an id like bob-jones-2.

        When the email address is used as login name, we originally
        used the email address as user id as well.  This has a few
        possible downsides, which are the main reasons for the new,
        pluggable approach:

        - It does not work for some valid email addresses.

        - Exposing the email address in this way may not be wanted.

        - When the user later changes his email address, the user id
          will still be his old address.  It works, but may be
          confusing.

        Another possibility would be to simply generate a uuid, but that
        is ugly.  We could certainly try that though: the big plus here
        would be that you then cannot create a new user with the same user
        id as a previously existing user if this ever gets removed.  If
        you would get the same id, this new user would get the same global
        and local roles, if those have not been cleaned up.

        When a user id is chosen, the 'user_id' key of the data gets
        set and the user id is returned.
        """
        generator = queryUtility(IUserIdGenerator)
        if generator:
            userid = generator(data)
            if userid:
                data['user_id'] = userid
                return userid

        settings = self._get_security_settings()
        if settings.use_uuid_as_userid:
            userid = uuid_userid_generator()
            data['user_id'] = userid
            return userid

        # We may have a username already.
        userid = data.get('username')
        if userid:
            # If we are not using email as login, then this user name is fine.
            if not settings.use_email_as_login:
                data['user_id'] = userid
                return userid

        # First get a default value that we can return if we cannot
        # find anything better.
        pas = getToolByName(self.context, 'acl_users')
        email = pas.applyTransform(data.get('email'))
        default = data.get('username') or email or ''
        data['user_id'] = default
        fullname = data.get('fullname')
        if not fullname:
            return default
        userid = normalizeString(fullname)
        # First check that this is a valid member id, regardless of
        # whether a member with this id already exists or not.  We
        # access an underscore attribute of the registration tool, so
        # we take a precaution in case this is ever removed as an
        # implementation detail.
        registration = getToolByName(self.context, 'portal_registration')
        if hasattr(registration, '_ALLOWED_MEMBER_ID_PATTERN'):
            if not registration._ALLOWED_MEMBER_ID_PATTERN.match(userid):
                # If 'bob-jones' is not good then 'bob-jones-1' will not
                # be good either.
                return default
        if registration.isMemberIdAllowed(userid):
            data['user_id'] = userid
            return userid
        # Try bob-jones-1, bob-jones-2, etc.
        idx = 1
        while idx <= RENAME_AFTER_CREATION_ATTEMPTS:
            new_id = "%s-%d" % (userid, idx)
            if registration.isMemberIdAllowed(new_id):
                data['user_id'] = new_id
                return new_id
            idx += 1

        # We cannot come up with a nice id, so we simply return the default.
        return default

    def generate_login_name(self, data):
        """Generate a login name from data.

        Usually the login name and user id are the same, but this is
        not necessarily true.  When using the email address as login
        name, we may have a different user id, generated by calling
        the generate_user_id method.

        We try a few options for coming up with a good login name:

        1. We query a utility, so integrators can register a hook to
           generate a login name using their own logic.

        2. If a username is given and we do not use email as login,
           then we simply return that username as the login name.

        3. When using email as login, we use the email address.

        In all cases, we call PAS.applyTransform on the login name, if
        that is defined.  This is a recent addition to PAS, currently
        under development.

        When a login name is chosen, the 'login_name' key of the data gets
        set and the login name is returned.
        """
        pas = getToolByName(self.context, 'acl_users')
        generator = queryUtility(ILoginNameGenerator)
        if generator:
            login_name = generator(data)
            if login_name:
                login_name = pas.applyTransform(login_name)
                data['login_name'] = login_name
                return login_name

        # We may have a username already.
        login_name = data.get('username')
        login_name = pas.applyTransform(login_name)
        data['login_name'] = login_name
        settings = self._get_security_settings()
        # If we are not using email as login, then this user name is fine.
        if not settings.use_email_as_login:
            return login_name

        # We use email as login.
        login_name = data.get('email')
        login_name = pas.applyTransform(login_name)
        data['login_name'] = login_name
        return login_name

    # Actions validators
    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')

        error_keys = [
            error.field.getName() for error in action.form.widgets.errors
        ]

        form_field_names = [f for f in self.fields]

        portal = getUtility(ISiteRoot)

        # 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 = data.get('password')
                password_ctl = data.get('password_ctl')
                if password != password_ctl:
                    err_str = _(u'Passwords do not match.')
                    notifyWidgetActionExecutionError(action, 'password',
                                                     err_str)
                    notifyWidgetActionExecutionError(action, 'password_ctl',
                                                     err_str)

        # Password field checked against RegistrationTool
        if 'password' in form_field_names:
            # Skip this check if password fields already have an error
            if 'password' not in error_keys:
                password = data.get('password')
                if password:
                    # Use PAS to test validity
                    err_str = registration.testPasswordValidity(password)
                    if err_str:
                        notifyWidgetActionExecutionError(
                            action, 'password', err_str)

        settings = self._get_security_settings()
        if settings.use_email_as_login:
            username_field = 'email'
        else:
            username_field = 'username'

        # The term 'username' is not clear.  It may be the user id or
        # the login name.  So here we try to be explicit.

        # Generate a nice user id and store that in the data.
        user_id = self.generate_user_id(data)
        # Generate a nice login name and store that in the data.
        login_name = self.generate_login_name(data)

        # Do several checks to see if the user id and the login name
        # are valid.
        #
        # Skip these checks if username was already in error list.
        #
        # Note that if we cannot generate a unique user id, it is not
        # necessarily the fault of the username field, but it
        # certainly is the most likely cause in a standard Plone
        # setup.

        # check if username is valid
        # Skip this check if username was already in error list
        if username_field not in error_keys:
            # user id may not be the same as the portal id.
            if user_id == portal.getId():
                err_str = _(u"This username is reserved. Please choose a "
                            "different name.")
                notifyWidgetActionExecutionError(action, username_field,
                                                 err_str)

        # Check if user id is allowed by the member id pattern.
        if username_field not in error_keys:
            if not registration.isMemberIdAllowed(user_id):
                err_str = _(u"The login name you selected is already in use "
                            "or is not valid. Please choose another.")
                notifyWidgetActionExecutionError(action, username_field,
                                                 err_str)

        if username_field not in error_keys:
            # Check the uniqueness of the login name, not only when
            # use_email_as_login is true, but always.
            pas = getToolByName(self, 'acl_users')
            results = pas.searchUsers(name=login_name, exact_match=True)
            if results:
                err_str = _(u"The login name you selected is already in use "
                            "or is not valid. Please choose another.")
                notifyWidgetActionExecutionError(action, username_field,
                                                 err_str)

        if 'password' in form_field_names and 'password' not in error_keys:
            # Admin can either set a password or mail the user (or both).
            if not (data['password'] or data['mail_me']):
                err_str = _('msg_no_password_no_mail_me',
                            default=u"You must set a password or choose to "
                            "send an email.")

                # set error on password field
                notifyWidgetActionExecutionError(action, 'password', err_str)
                notifyWidgetActionExecutionError(action, 'mail_me', err_str)

    @button.buttonAndHandler(_(u'label_register', default=u'Register'),
                             name='register')
    def action_join(self, action):
        data, errors = self.extractData()

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

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

        self.handle_join_success(data)

        self._finishedRegister = True

        # XXX Return somewhere else, depending on what
        # handle_join_success returns?
        came_from = self.request.form.get('came_from')
        if came_from:
            utool = getToolByName(self.context, 'portal_url')
            if utool.isURLInPortal(came_from):
                self.request.response.redirect(came_from)
                return ''

    def handle_join_success(self, data):
        # portal should be acquisition wrapped, this is needed for the schema
        # adapter below
        portal = getToolByName(self.context, 'portal_url').getPortalObject()
        registration = getToolByName(self.context, 'portal_registration')

        # user_id and login_name should be in the data, but let's be safe.
        user_id = data.get('user_id', data.get('username'))
        login_name = data.get('login_name', data.get('username'))
        # I have seen a unicode user id.  I cannot reproduce it, but
        # let's make them strings, otherwise you run into trouble with
        # plone.session when trying to login.
        if isinstance(user_id, unicode):
            user_id = user_id.encode('utf8')
        if isinstance(login_name, unicode):
            login_name = login_name.encode('utf8')

        # Set the username for good measure, as some code may expect
        # it to exist and contain the user id.
        data['username'] = user_id

        # The login name may already be in the form, but not
        # necessarily, for example when using email as login.  This is
        # at least needed for logging in immediately when password
        # reset is bypassed.  We need the login name here, not the
        # user id.
        self.request.form['form.username'] = login_name

        password = data.get('password') or registration.generatePassword()
        if isinstance(password, unicode):
            password = password.encode('utf8')

        try:
            registration.addMember(user_id, password, REQUEST=self.request)
        except (AttributeError, ValueError), err:
            logging.exception(err)
            IStatusMessage(self.request).addStatusMessage(err, type="error")
            return

        if user_id != login_name:
            # The user id differs from the login name.  Set the login
            # name correctly.
            pas = getToolByName(self.context, 'acl_users')
            pas.updateLoginName(user_id, login_name)

        # set member properties
        self.applyProperties(user_id, data)

        settings = self._get_security_settings()
        if data.get('mail_me') or (not settings.enable_user_pwd_choice
                                   and not data.get('password')):
            # We want to validate the email address (users cannot
            # select their own passwords on the register form) or the
            # admin has explicitly requested to send an email on the
            # 'add new user' form.
            try:
                # When all goes well, this call actually returns the
                # rendered mail_password_response template.  As a side
                # effect, this removes any status messages added to
                # the request so far, as they are already shown in
                # this template.
                response = registration.registeredNotify(user_id)
                return response
            except ConflictError:
                # Let Zope handle this exception.
                raise
            except Exception:
                ctrlOverview = getMultiAdapter((portal, self.request),
                                               name='overview-controlpanel')
                mail_settings_correct = not ctrlOverview.mailhost_warning()
                if mail_settings_correct:
                    # The email settings are correct, so the most
                    # likely cause of an error is a wrong email
                    # address.  We remove the account:
                    # Remove the account:
                    self.context.acl_users.userFolderDelUsers(
                        [user_id], REQUEST=self.request)
                    IStatusMessage(self.request).addStatusMessage(_(
                        u'status_fatal_password_mail',
                        default=u"Failed to create your account: we were "
                        "unable to send instructions for setting a password "
                        "to your email address: ${address}",
                        mapping={u'address': data.get('email', '')}),
                                                                  type='error')
                    return
                else:
                    # This should only happen when an admin registers
                    # a user.  The admin should have seen a warning
                    # already, but we warn again for clarity.
                    IStatusMessage(self.request).addStatusMessage(
                        _(u'status_nonfatal_password_mail',
                          default=u"This account has been created, but we "
                          "were unable to send instructions for setting a "
                          "password to this email address: ${address}",
                          mapping={u'address': data.get('email', '')}),
                        type='warning')
                    return

        return
Exemplo n.º 33
0
    def __call__(self):
        # if self.descriptor.startswith('D1.'):       # map to old descriptor
        #     # self._descriptor = 'D1'               # this hardcodes D1.x
        #                                             # descriptors to D1
        #     assert self.descriptor == 'D1'

        if 'translate' in self.request.form:
            report_view = self.get_report_view()
            report_view.auto_translate()

            messages = IStatusMessage(self.request)
            messages.add(
                u"Auto-translation initiated, please refresh "
                u"in a couple of minutes",
                type=u"info")

        print("Will render report for: %s" % self.article)
        self.filename = filename = self.get_report_filename()
        factsheet = None

        source_file = ('File not found', None)
        multiple_source_files = False

        if filename:
            if isinstance(filename, tuple):
                multiple_source_files = True
                try:
                    source_file = [
                        (f, get_report_file_url(f) + '/manage_document')
                        for f in filename
                    ]
                except:
                    logger.exception("Error in getting HTML Factsheet URL)")
            else:
                url = get_report_file_url(filename)
                if url:
                    try:
                        factsheet = get_factsheet_url(url)
                    except Exception:
                        logger.exception(
                            "Error in getting HTML Factsheet URL %s", url)
                else:
                    logger.warning("No factsheet url, filename is: %r",
                                   filename)

                source_file = (filename, url + '/manage_document')

        rep_info = self.get_reporting_information()

        report_header_data = self.get_report_header_data(
            rep_info.reporters, source_file, factsheet, rep_info.report_date,
            multiple_source_files)
        report_header = self.report_header_template(**report_header_data)
        try:
            report_data, report_data_rows = self.get_report_data()
        except:
            report_data, report_data_rows = 'Error in rendering report', []
        trans_edit_html = self.translate_view()()
        self.report_html = report_header + report_data + trans_edit_html

        if 'download' in self.request.form:

            return self.download(report_data_rows, report_header_data)

        return self.index()
Exemplo n.º 34
0
 def handleCancel(self, action):
     IStatusMessage(self.request).addStatusMessage(_(u'Edit cancelled'),
                                                   'info')
     self.request.response.redirect(
         '%s/%s' % (self.context.absolute_url(), self.control_panel_view))
Exemplo n.º 35
0
 def handleCancel(self, action):
     IStatusMessage(self.request).addStatusMessage(_(u"Edit cancelled"),
                                                   "info")
     self.request.response.redirect(self.nextURL())
     notify(EditCancelledEvent(self.context))
Exemplo n.º 36
0
class ReportStylesView(object):
    """View for report style control"""
    def __init__(self, context, request):
        self.context = context  # IDataReport
        self.request = request
        self.status = IStatusMessage(self.request)
        # uncached initial values:
        self.show_paste = False
        self._contained = None
        self._charts = None
        self._stylebooks = None

    def can_paste_stylebooks(self):
        if self.request.get('__cp', None) is not None:
            if self.context.cb_dataValid():
                oblist = self.context.cb_dataItems()
                if oblist:
                    return all(
                        map(
                            lambda o: IChartStyleBook.providedBy(o),
                            oblist,
                        ))
        return False

    @property
    def contained(self):
        if self._contained is None:
            self._contained = self.context.objectValues()
        return self._contained

    def charts(self):
        if self._charts is None:
            self._charts = filter(
                lambda o: o.portal_type in CHART_TYPES,
                self.contained,
            )
        return self._charts

    def stylebooks(self):
        if self._stylebooks is None:
            self._stylebooks = filter(
                lambda o: o.portal_type == STYLEBOOK_TYPE,
                self.contained,
            )
        return self._stylebooks

    def update_apply(self, *args, **kwargs):
        req = self.request
        do_bind = bool(req.get('bind-stylebook', False))
        _get = lambda name: self.context.get(name, None)
        stylebook = _get(req.get('selected-stylebook'))
        if stylebook is None:
            self.status.addStatusMessage('Unknonwn style book', type='info')
            return
        targets = [_get(name) for name in req.get('selected-charts', [])]
        if not targets:
            self.status.addStatusMessage(
                'No target charts selected to apply stylebook to.',
                type='info')
            return
        for target in targets:
            clone_chart_styles(stylebook, target)  # copy styles now
            if do_bind:
                bookuid = IUUID(stylebook, None)
                target.stylebook = bookuid
        _listcharts = lambda s: ', '.join(['"%s"' % o.Title() for o in s])
        msg = 'Copied styles from' if not do_bind else 'Bound'
        self.status.addStatusMessage(
            '%s stylebook "%s" to %s charts: %s' % (
                msg,
                stylebook.Title(),
                len(targets),
                _listcharts(targets),
            ),
            type='info',
        )
        if do_bind:
            self.status.addStatusMessage(
                'IMPORTANT: subsequent changes to style book and line '
                'styles will propogate to the charts listed as bound '
                'to a style book.  To remove a binding, visit the Edit '
                'tab of a chart that has been bound to a style book this '
                'way.',
                type='info',
            )

    def _stylebook_title(self):
        """get next stylebook title"""
        base = u'Style book %s'
        books = self.stylebooks()
        if not books:
            return base % 1
        titles = [o.Title() for o in books]
        isdigit = lambda s: s in [str(i) for i in range(0, 10)]
        autonames = sorted([
            title for title in titles
            if title.startswith(base[:-2]) and isdigit(title[-1])
        ])
        if not autonames:
            return base % 1
        lastnum = int(autonames[-1].split(' ')[-1])
        return base % (lastnum + 1)

    def update_mimic(self, *args, **kwargs):
        req = self.request
        mimic = req.get('existing-charts', None)
        mimic = self.context.get(mimic, None)
        if not mimic:
            self.status.addStatusMessage('Unable to locate existing chart',
                                         type='warning')
            return
        linecount = len(mimic.objectIds())
        title = self._stylebook_title()
        stylebook = createContentInContainer(
            self.context,
            STYLEBOOK_TYPE,
            title=title,
        )
        for i in range(linecount):
            createContentInContainer(
                stylebook,
                LINESTYLE_TYPE,
                title=u'Line style %s' % i,
            )
        clone_chart_styles(source=mimic, target=stylebook)
        self._contained = self._stylebooks = None  # un-cache now outdated
        self.status.addStatusMessage(
            'Created a new stylebook "%s" based on styles of existing chart '
            '"%s".' % (title, mimic.Title()),
            type='info',
        )

    def update(self, *args, **kwargs):
        self.show_paste = self.can_paste_stylebooks()
        req = self.request
        if req.get('REQUEST_METHOD', 'GET') == 'POST':
            if 'apply-stylebook' in req.form or 'bind-stylebook' in req.form:
                self.update_apply(*args, **kwargs)
            if 'existing-mimic' in req.form:
                self.update_mimic(*args, **kwargs)

    def __call__(self, *args, **kwargs):
        self.update(*args, **kwargs)
        return self.index(*args, **kwargs)  # provided by template via Five
Exemplo n.º 37
0
class ComposedForm(AutoExtensibleForm, form.Form):
    """
    A form composed from multiple schema adapting a form definition.
    This composition uses (base class from) plone.autoform to compose
    a merged form.
    """

    ignoreContext = True  # form operates without edit context.

    # autoGroups here requires plone.autoform >= 1.6 for anonymous schema:
    autoGroups = True

    enable_form_tabbing = False  # do not display fieldsets in tabs.

    # schema must be property, not attribute for AutoExtensibleForm sublcass
    @property
    def schema(self):
        return self._schema

    @property
    def additionalSchemata(self):
        return self._additionalSchemata

    def __init__(self, context, request, name=None):
        """
        Construct composed form given (default) schema an a tuple
        of ordered additional schema key/value pairs of (string)
        component name keys to schema values.
        """
        self.context = context
        self.request = request
        # form definition will either be context, or adaptation of context.
        # see uu.formlibrary.definition.form_definition for adapter example.
        if name is None:
            self.definition = IFormDefinition(self.context)
        else:
            self.definition = queryAdapter(
                self.context,
                IFormDefinition,
                name=name,
            )
        self._schema = self.definition.schema
        self.groups = []  # modified by updateFieldsFromSchemata()

        self.components = IFormComponents(self.definition)
        self.group_schemas = self._group_schemas()
        self.group_titles = self._group_titles()

        # mapping: schema to names:
        self.schema_names = dict(invert(self.group_schemas))

        # ordered list of additional schema for AutoExtensibleForm:
        self._additionalSchemata = tuple(
            [t[1] for t in self.group_schemas if t[0]])
        # super(ComposedForm, self).__init__(self, context, request)
        form.Form.__init__(self, context, request)
        self.saved = False  # initial value: no duplication of save...
        self.save_attempt = False  # flag for save attempt, success or not
        self._status = IStatusMessage(self.request)

    def _group_schemas(self):
        result = []
        for name in self.components.names:
            group = self.components.groups[name]
            schema = group.schema
            if group.group_usage == u'grid':
                schema = grid_wrapper_schema(schema)
            result.append((name, schema))
        return result

    def _group_titles(self):
        result = {}
        for name, group in self.components.groups.items():
            result[name] = group.Title()
        return result

    def updateFieldsFromSchemata(self):
        self.groups = []
        for name, schema in self.group_schemas:
            if name == '':
                continue  # default, we don't need another group
            title = self.group_titles.get(name, name)
            fieldset_group = GroupFactory(name, field.Fields(), title)
            self.groups.append(fieldset_group)
        super(ComposedForm, self).updateFieldsFromSchemata()

    def _load_widget_data(self):
        _marker = object()
        data = aq_base(self.context).data
        groups = dict((g.__name__, g) for g in self.groups)
        groupnames = [''] + groups.keys()
        for groupname in groupnames:
            group_data = data.get(groupname, None)
            if groupname is '':
                group = self
            else:
                group = groups.get(groupname)
                fieldgroup = self.definition[groupname]
                # # plone.autoform binds groups really, really late, so
                # # we are stuck with a GroupFactory object, we need to
                # # call it to get the actual group, then replace the
                # # group factory with it once we have manipulated
                # # any widget values:
                if IGroupFactory.providedBy(group):
                    idx = self.groups.index(group)
                    actual_group = group(self.context, self.request, self)
                    self.groups[idx] = group = actual_group
                    group.update()  # will populate group.widgets
                if group_data and fieldgroup.group_usage == 'grid':
                    data_widget = group.widgets.values()[0]
                    data_widget.value = getattr(group_data, 'data', [])
                    continue

            if group_data is not None:
                for formfield in group.fields.values():
                    schema_field = formfield.field
                    widgetname = formfield.__name__
                    fieldname = schema_field.__name__
                    v = getattr(group_data, fieldname, _marker)
                    if v is not _marker:
                        widget = group.widgets.get(widgetname)
                        conv = getMultiAdapter(
                            (schema_field, widget),
                            IDataConverter,
                        )
                        if not IDataGridField.providedBy(widget):
                            v = conv.toWidgetValue(v)
                        widget.value = v
                        if hasattr(widget, 'update'):
                            # may be necessary to copy value to other state,
                            # as is the case with radio button widgets
                            widget.update()
                            # multiple collection like set/list (multi-choice)
                            # has issues where SequenceWidget wants to reset
                            # widget.value during update... so we have to
                            # check the value (ugly hack) and also re-set the
                            # value for the display widget:
                            if ICollection.providedBy(schema_field):
                                widget.value = v
                                if v:
                                    term_item = [
                                        t for t in widget.items
                                        if t.get('value') == v[0]
                                    ][0]
                                    term_item['checked'] = True

    def updateWidgets(self):
        common_widget_updates(self)
        for group in self.groups:
            common_widget_updates(group)
        super(ComposedForm, self).updateWidgets()
        # # finally, if non-defintion context, set widget values via group data
        if not IFormDefinition.providedBy(self.context):
            self._load_widget_data()

    def datagridInitialise(self, subform, widget):
        if not hasattr(self, '_widgets_initialized'):
            self._widgets_initialized = []  # don't duplicate effort!
        if subform not in self._widgets_initialized:
            date_fields = [
                f for f in subform.fields.values() if IDate.providedBy(f.field)
            ]
            for formfield in date_fields:
                formfield.widgetFactory = TypeADateFieldWidget
        self._widgets_initialized.append(subform)

    def getPrefix(self, schema):
        if schema in self.schema_names:
            return self.schema_names[schema]
        # fall-back will not work for anoymous schema without names, but
        # it is the best we can assume to do here:
        return super(ComposedForm, self).getPrefix(schema)

    def _saveResult(self, result):
        schemas = dict(self.group_schemas)
        for name, values in result.items():
            name = str(name)
            schema = schemas.get(name, self._schema)  # schema or default group
            if schema:
                group_record = self.context.data.get(name, None)
                if group_record is None:
                    group_record = self.context.data[name] = FormEntry()
                group_record.sign(schema)
                for fieldname, value in values.items():
                    setattr(group_record, fieldname, value)

    def _handleSave(self, action, msg='Saved form data'):
        self.save_attempt = True
        data, errors = self.extractData()
        if errors or IFormDefinition.providedBy(self.context) or self.saved:
            return False  # just validate if errors, or if context if defn
        if not self.saved:
            result = {}  # submitted data. k: group name; v: dict of name/value
            group_keys = []
            for group in self.groups:
                groupdata = {}
                form_group_data = group.extractData()[0]
                for name, _field in group.fields.items():
                    group_keys.append(name)
                    fieldname = _field.field.__name__
                    default = getattr(_field.field, 'default', None)
                    field_data = form_group_data.get(name, default)
                    if ICollection.providedBy(_field.field):
                        if isinstance(_field.field.value_type, DictRow):
                            is_nonempty_row = lambda v: any(v.values())
                            field_data = filter(is_nonempty_row, field_data)
                    groupdata[fieldname] = field_data
                result[group.__name__] = groupdata
            # filter default fieldset values, ignore group values in data dict:
            result[''] = dict([(k, v) for k, v in data.items()
                               if k not in group_keys])
            self._saveResult(result)
            self.saved = True
            history_log(self.context, message=msg, set_modified=True)
            notify(ObjectModifiedEvent(self.context))
            transaction.get().note(msg)
        self._status.addStatusMessage('Saved form data', type='info')
        return True

    @button.buttonAndHandler(u'\u2714 Save draft',
                             condition=lambda form: form.mode == 'input')
    def handleSave(self, action):
        self._handleSave(action)

    @button.buttonAndHandler(u'\u21E5 Save and submit',
                             condition=lambda form: form.mode == 'input')
    def handleSaveSubmit(self, action):
        saved = self._handleSave(action)
        if not saved:
            return  # no status change, no 302 -- validation errors to user
        wftool = getToolByName(self.context, 'portal_workflow')
        chain = wftool.getChainFor(self.context)[0]
        state = wftool.getStatusOf(chain, self.context)['review_state']
        if state == 'visible':
            wftool.doActionFor(self.context, 'submit')
            self.context.reindexObject()
            self._status.addStatusMessage('Form submitted for review',
                                          type='info')
            url = self.context.absolute_url()
            self.request.RESPONSE.redirect(url)
Exemplo n.º 38
0
    def enumerateGroups(self,
                        id=None,
                        exact_match=False,
                        sort_by=None,
                        max_results=None,
                        **kw):
        """ -> ( group_info_1, ... group_info_N )

        o Return mappings for groups matching the given criteria.

        o 'id' in combination with 'exact_match' true, will
          return at most one mapping per supplied ID ('id' and 'login'
          may be sequences).

        o If 'exact_match' is False, then 'id' may be treated by
          the plugin as "contains" searches (more complicated searches
          may be supported by some plugins using other keyword arguments).

        o If 'sort_by' is passed, the results will be sorted accordingly.
          known valid values are 'id' (some plugins may support others).

        o If 'max_results' is specified, it must be a positive integer,
          limiting the number of returned mappings.  If unspecified, the
          plugin should return mappings for all groups satisfying the
          criteria.

        o Minimal keys in the returned mappings:

          'id' -- (required) the group ID

          'pluginid' -- (required) the plugin ID (as returned by getId())

          'properties_url' -- (optional) the URL to a page for updating the
                              group's properties.

          'members_url' -- (optional) the URL to a page for updating the
                           principals who belong to the group.

        o Plugin *must* ignore unknown criteria.

        o Plugin may raise ValueError for invalid critera.

        o Insufficiently-specified criteria may have catastrophic
          scaling issues for some implementations.
        """
        default = ()
        if not self.is_plugin_active(pas_interfaces.IGroupEnumerationPlugin):
            return default
        groups = self.groups
        if not groups:
            return default
        if id and exact_match:
            if id in self.getGroupIds():
                return ({'id': id, 'pluginid': self.getId()})
            else:
                return default
        elif id:
            kw['id'] = id
        if not kw:  # show all
            matches = groups.ids
        else:
            matches = []
            cookie = None
            while True:
                try:
                    res = groups.search(
                        criteria=encode(kw),
                        attrlist=None,
                        exact_match=exact_match,
                        page_size=self._ldap_props.page_size,
                        cookie=cookie,
                    )
                    if isinstance(res, tuple):
                        batch_matches, cookie = res
                    else:
                        batch_matches, cookie = res, ''
                except ValueError:
                    return default
                matches += batch_matches
                if not cookie:
                    break
        if len(matches) >= 100:
            msg = 'Too many search results. Please, narrow your search.'
            IStatusMessage(self.REQUEST).add(msg, type='warning')
            return default
        if sort_by == 'id':
            matches = sorted(matches)
        pluginid = self.getId()
        ret = list()
        if exact_match:
            for id, attrs in matches:
                ret.append({'id': id, 'pluginid': pluginid})
        else:
            for id in matches:
                ret.append({'id': id, 'pluginid': pluginid})
        if max_results and len(ret) > max_results:
            ret = ret[:max_results]
        return ret
Exemplo n.º 39
0
    def update(self):
        # XXX: complexity too high: refactoring needed
        processInputs(self.request)
        self._setup()
        self.errors = {}
        form = self.request.form

        if 'form.button.Cancel' in form:
            IStatusMessage(self.request).add(_(u"Changes cancelled"))
            self.redirect("{0}/@@overview-controlpanel".format(self.site_url))
            return False

        if 'form.button.Enable' in form:
            self.authorize()

            themeSelection = form.get('themeName', None)

            if themeSelection:
                themeData = self.getThemeData(self.availableThemes,
                                              themeSelection)
                applyTheme(themeData)
                self.theme_settings.enabled = True

            IStatusMessage(self.request).add(
                _(u"Theme enabled. Note that this control panel page is "
                  u"never themed."))
            self._setup()
            return True

        if 'form.button.InvalidateCache' in form:
            self.authorize()
            policy = theming_policy()
            policy.invalidateCache()
            return True

        if 'form.button.Disable' in form:
            self.authorize()

            applyTheme(None)
            self.theme_settings.enabled = False

            IStatusMessage(self.request).add(_(u"Theme disabled."))
            self._setup()
            return True

        if 'form.button.AdvancedSave' in form:
            self.authorize()

            self.theme_settings.readNetwork = form.get('readNetwork', False)

            themeEnabled = form.get('themeEnabled', False)
            rules = form.get('rules', None)
            prefix = form.get('absolutePrefix', None)
            doctype = str(form.get('doctype', ""))

            hostnameBlacklist = form.get('hostnameBlacklist', [])

            parameterExpressions = {}
            parameterExpressionsList = form.get('parameterExpressions', [])

            for line in parameterExpressionsList:
                try:
                    name, expression = line.split('=', 1)
                    name = str(name.strip())
                    expression = str(expression.strip())
                    parameterExpressions[name] = expression
                except ValueError:
                    message = _(
                        'error_invalid_parameter_expressions',
                        default=u"Please ensure you enter one expression per "
                        u"line, in the format <name> = <expression>.")
                    self.errors['parameterExpressions'] = message

            themeBase = form.get('themeBase', None)
            markSpecialLinks = form.get('markSpecialLinks', None)
            extLinksOpenInNewWindow = form.get('extLinksOpenInNewWindow', None)

            if not self.errors:
                # Trigger onDisabled() on plugins if theme was active
                # previously and rules were changed
                if self.theme_settings.rules != rules:
                    applyTheme(None)

                self.theme_settings.enabled = themeEnabled
                self.theme_settings.rules = rules
                self.theme_settings.absolutePrefix = prefix
                self.theme_settings.parameterExpressions = parameterExpressions
                self.theme_settings.hostnameBlacklist = hostnameBlacklist
                self.theme_settings.doctype = doctype

                # Theme base settings
                if themeBase is not None:
                    self.pskin.default_skin = themeBase.encode('utf-8')
                if markSpecialLinks is not None:
                    self.mark_special_links = markSpecialLinks
                if extLinksOpenInNewWindow is not None:
                    self.ext_links_open_new_window = extLinksOpenInNewWindow

                IStatusMessage(self.request).add(_(u"Changes saved"))
                self._setup()
                return True
            else:
                IStatusMessage(self.request).add(_(u"There were errors"),
                                                 'error')
                self.redirectToFieldset('advanced')
                return False

        if 'form.button.Import' in form:
            self.authorize()

            enableNewTheme = form.get('enableNewTheme', False)
            replaceExisting = form.get('replaceExisting', False)
            themeArchive = form.get('themeArchive', None)

            themeZip = None
            performImport = False

            try:
                themeZip = zipfile.ZipFile(themeArchive)
            except (
                    zipfile.BadZipfile,
                    zipfile.LargeZipFile,
            ):
                logger.exception("Could not read zip file")
                self.errors['themeArchive'] = _(
                    'error_invalid_zip',
                    default=u"The uploaded file is not a valid Zip archive")

            if themeZip:

                try:
                    themeData = extractThemeInfo(themeZip, checkRules=False)
                except (
                        ValueError,
                        KeyError,
                ), e:
                    logger.warn(str(e))
                    self.errors['themeArchive'] = _(
                        'error_no_rules_file',
                        u"The uploaded file does not contain a valid theme "
                        u"archive.")
                else:

                    themeContainer = getOrCreatePersistentResourceDirectory()
                    themeExists = themeData.__name__ in themeContainer

                    if themeExists:
                        if not replaceExisting:
                            self.errors['themeArchive'] = _(
                                'error_already_installed',
                                u"This theme is already installed. Select "
                                u"'Replace existing theme' and re-upload to "
                                u"replace it.")
                        else:
                            del themeContainer[themeData.__name__]
                            performImport = True
                    else:
                        performImport = True

            if performImport:
                themeContainer.importZip(themeZip)

                themeDirectory = queryResourceDirectory(
                    THEME_RESOURCE_NAME, themeData.__name__)
                if themeDirectory is not None:
                    # If we don't have a rules file, use the template
                    if themeData.rules == u"/++{0:s}++{1:s}/{2:s}".format(
                            THEME_RESOURCE_NAME,
                            themeData.__name__,
                            RULE_FILENAME,
                    ) and not themeDirectory.isFile(RULE_FILENAME):
                        templateThemeDirectory = queryResourceDirectory(
                            THEME_RESOURCE_NAME, TEMPLATE_THEME)
                        themeDirectory.writeFile(
                            RULE_FILENAME,
                            templateThemeDirectory.readFile(RULE_FILENAME))

                        if not themeDirectory.isFile(DEFAULT_THEME_FILENAME):
                            IStatusMessage(self.request).add(
                                _(u"A boilerplate rules.xml was added to "
                                  u"your theme, but no index.html file "
                                  u"found. Update rules.xml to reference "
                                  u"the current theme file."),
                                'warning',
                            )

                    plugins = getPlugins()
                    pluginSettings = getPluginSettings(themeDirectory, plugins)
                    if pluginSettings is not None:
                        for name, plugin in plugins:
                            plugin.onCreated(themeData.__name__,
                                             pluginSettings[name],
                                             pluginSettings)

                if enableNewTheme:
                    applyTheme(themeData)
                    self.theme_settings.enabled = True

            if not self.errors:
                self.redirect(
                    "{0}/++theme++{1}/@@theming-controlpanel-mapper".format(
                        self.site_url, themeData.__name__))
                return False
            else:
                IStatusMessage(self.request).add(_(u"There were errors"),
                                                 "error")

                self.renderOverlay('upload')
                return True
Exemplo n.º 40
0
    def enumerateUsers(self,
                       id=None,
                       login=None,
                       exact_match=False,
                       sort_by=None,
                       max_results=None,
                       **kw):
        """-> ( user_info_1, ... user_info_N )

        o Return mappings for users matching the given criteria.

        o 'id' or 'login', in combination with 'exact_match' true, will
          return at most one mapping per supplied ID ('id' and 'login'
          may be sequences).

        o If 'exact_match' is False, then 'id' and / or login may be
          treated by the plugin as "contains" searches (more complicated
          searches may be supported by some plugins using other keyword
          arguments).

        o If 'sort_by' is passed, the results will be sorted accordingly.
          known valid values are 'id' and 'login' (some plugins may support
          others).

        o If 'max_results' is specified, it must be a positive integer,
          limiting the number of returned mappings.  If unspecified, the
          plugin should return mappings for all users satisfying the criteria.

        o Minimal keys in the returned mappings:

          'id' -- (required) the user ID, which may be different than
                  the login name

          'login' -- (required) the login name

          'pluginid' -- (required) the plugin ID (as returned by getId())

          'editurl' -- (optional) the URL to a page for updating the
                       mapping's user

        o Plugin *must* ignore unknown criteria.

        o Plugin may raise ValueError for invalid criteria.

        o Insufficiently-specified criteria may have catastrophic
          scaling issues for some implementations.
        """
        default = tuple()
        if not self.is_plugin_active(pas_interfaces.IUserEnumerationPlugin):
            return default
        # TODO: sort_by in node.ext.ldap
        if login:
            if not isinstance(login, basestring):
                # XXX TODO
                raise NotImplementedError('sequence is not supported yet.')
            kw['login'] = login

        # pas search users gives both login and name if login is meant
        if "login" in kw and "name" in kw:
            del kw["name"]

        if id:
            if not isinstance(id, basestring):
                # XXX TODO
                raise NotImplementedError('sequence is not supported yet.')
            kw['id'] = id
        users = self.users
        if not users:
            return default
        if not exact_match:
            for value in users.principal_attrmap.values():
                kw[value] = kw.values()[0]
        matches = []
        cookie = None
        while True:
            try:
                res = users.search(
                    criteria=encode(kw),
                    attrlist=exact_match and users.context.search_attrlist
                    or ['login'],
                    exact_match=exact_match,
                    or_search=not exact_match,
                    page_size=not exact_match and self._ldap_props.page_size
                    or None,
                    cookie=cookie,
                )
                if isinstance(res, tuple):
                    batch_matches, cookie = res
                else:
                    batch_matches, cookie = res, ''
            except ValueError:
                return default
            matches += batch_matches
            if not cookie:
                break
        if len(matches) >= 100:
            msg = 'Too many search results. Please, narrow your search.'
            IStatusMessage(self.REQUEST).add(msg, type='warning')
            return default
        pluginid = self.getId()
        ret = list()
        for id, attrs in matches:
            if 'login' not in attrs:
                continue
            ret.append({
                'id': id,
                'login': attrs['login'][0],
                'pluginid': pluginid
            })
        if max_results and len(ret) > max_results:
            ret = ret[:max_results]
        return ret
Exemplo n.º 41
0
    def __call__(self):
        self.request.set('disable_border', True)
        self.errors = {}

        props = getToolByName(self.context,
                              'portal_properties').pcommerce_properties
        if self.request.form.has_key('pcommerce_save'):
            adapter = ITaxes(self.context)
            taxes = []
            raw = self.request.form.get('taxes', [])
            for tax in raw:
                if not tax.has_key('remove') or not tax['remove']:
                    try:
                        tax = {
                            'id': tax['id'],
                            'tax': float(tax['tax']),
                            'zone': tax['zone'],
                            'taxname': tax['taxname']
                        }
                        if tax['zone'] == '':
                            self.errors[tax['id']] = _(
                                u'Please provide a zone name')
                        elif tax['taxname'] == '':
                            self.errors[tax['id']] = _(
                                u'Please provide a tax name')
                        if not self.errors.has_key(tax['id']):
                            taxes.append(tax)
                    except:
                        self.errors[tax['id']] = _(
                            u'Please enter a floating point number (e.g. 7.6)')
            for prop in self.properties:
                self.values[prop] = self.request.form.get(prop, '')

            taxincl = None
            tax = self.request.form.get('taxincl.tax', '')
            taxname = self.request.form.get('taxincl.taxname', '')

            try:
                if taxname == '' and tax != '':
                    self.errors['taxincl'] = _(u'Please provide a tax name')
                else:
                    if tax == '':
                        tax = 0.0
                    taxincl = (float(tax), taxname)
            except:
                self.errors['taxincl'] = _(
                    u'Please enter a floating point number (e.g. 7.6)')

            if not self.errors:
                adapter.edit(taxes)
                adapter.taxincl = taxincl
                IStatusMessage(self.request).addStatusMessage(
                    _p('Properties saved'), 'info')
                for prop in self.properties:
                    if prop == 'columns':
                        self.values[prop] = int(self.values[prop])
                    props._setPropValue(prop, self.values[prop])
            else:
                IStatusMessage(self.request).addStatusMessage(
                    _p(u'Please correct the indicated errors'), 'error')

        for prop in self.properties:
            self.values[prop] = props.getProperty(prop, '')

        return self.template()
Exemplo n.º 42
0
    def handle_continue(self, action):
        data, errors = self.extractData()

        if not errors:
            oguid = ISuccessorTaskController(self.context).get_oguid()

            # set forwarding flag
            if self.context.task_type == 'forwarding_task_type':
                is_forwarding = True
            else:
                is_forwarding = False

            dm = getUtility(IWizardDataStorage)
            dmkey = 'accept:%s' % oguid
            dm.set(dmkey, u'is_forwarding', is_forwarding)
            dm.set(dmkey, u'is_only_assign', False)
            dm.update(dmkey, data)

            method = data.get('method')

            if method == 'participate':
                accept_task_with_response(self.context, data['text'])
                IStatusMessage(self.request).addStatusMessage(
                    _(u'The task has been accepted.'), 'info')
                return self.request.response.redirect(
                    self.context.absolute_url())

            elif method == 'forwarding_participate':
                """only store the forwarding in the inbox and
                create a successor forwrding"""

                admin_unit = self.context.get_responsible_admin_unit()

                # push session data to target unit
                dm.push_to_remote_client(dmkey, admin_unit.id())
                url = '%s/@@accept_store_in_inbox?oguid=%s' % (
                    admin_unit.public_url, oguid)

                return self.request.RESPONSE.redirect(url)

            elif method == 'existing_dossier':
                admin_unit = self.context.get_responsible_admin_unit()

                # push session data to target unit
                dm.push_to_remote_client(dmkey, admin_unit.id())

                url = '%s/@@accept_choose_dossier?oguid=%s' % (
                    admin_unit.public_url, oguid)
                return self.request.RESPONSE.redirect(url)

            elif method == 'new_dossier':
                admin_unit = self.context.get_responsible_admin_unit()
                oguid = ISuccessorTaskController(self.context).get_oguid()

                # push session data to target client
                dm.push_to_remote_client(dmkey, admin_unit.id())

                url = '/'.join(
                    (admin_unit.public_url,
                     '@@accept_select_repositoryfolder?oguid=%s' % oguid))
                return self.request.RESPONSE.redirect(url)
Exemplo n.º 43
0
 def message(self, mensagem):
     messages = IStatusMessage(self.request)
     messages.add(mensagem, type='info')
     return
Exemplo n.º 44
0
class ThemingControlpanel(BrowserView):
    @property
    def site_url(self):
        """Return the absolute URL to the current site, which is likely not
        necessarily the portal root.
        """
        return getSite().absolute_url()

    def __call__(self):
        self.pskin = getToolByName(self.context, 'portal_skins')

        if self.update():
            return self.index()
        return ''

    def _setup(self):
        registry = getUtility(IRegistry)
        self.theme_settings = registry.forInterface(IThemeSettings, False)
        self.link_settings = registry.forInterface(ILinkSchema,
                                                   prefix="plone",
                                                   check=False)
        self.zodbThemes = getZODBThemes()
        self.availableThemes = getAvailableThemes()
        self.selectedTheme = self.getSelectedTheme(
            self.availableThemes, self.theme_settings.currentTheme,
            self.theme_settings.rules)
        self.overlay = ''

        self.skinsVocabulary = getUtility(IVocabularyFactory,
                                          name='plone.app.vocabularies.Skins')(
                                              self.context)

        # Set response header to make sure control panel is never themed
        self.request.response.setHeader('X-Theme-Disabled', '1')

    def redirect(self, url):
        self.request.response.redirect(url)

    def get_mark_special_links(self):
        return self.link_settings.mark_special_links

    def set_mark_special_links(self, value):
        self.link_settings.mark_special_links = value

    mark_special_links = property(get_mark_special_links,
                                  set_mark_special_links)

    def get_ext_links_open_new_window(self):
        return self.link_settings.external_links_open_new_window

    def set_ext_links_open_new_window(self, value):
        self.link_settings.external_links_open_new_window = value

    ext_links_open_new_window = property(get_ext_links_open_new_window,
                                         set_ext_links_open_new_window)

    def update(self):
        # XXX: complexity too high: refactoring needed
        processInputs(self.request)
        self._setup()
        self.errors = {}
        form = self.request.form

        if 'form.button.Cancel' in form:
            IStatusMessage(self.request).add(_(u"Changes cancelled"))
            self.redirect("{0}/@@overview-controlpanel".format(self.site_url))
            return False

        if 'form.button.Enable' in form:
            self.authorize()

            themeSelection = form.get('themeName', None)

            if themeSelection:
                themeData = self.getThemeData(self.availableThemes,
                                              themeSelection)
                applyTheme(themeData)
                self.theme_settings.enabled = True

            IStatusMessage(self.request).add(
                _(u"Theme enabled. Note that this control panel page is "
                  u"never themed."))
            self._setup()
            return True

        if 'form.button.InvalidateCache' in form:
            self.authorize()
            policy = theming_policy()
            policy.invalidateCache()
            return True

        if 'form.button.Disable' in form:
            self.authorize()

            applyTheme(None)
            self.theme_settings.enabled = False

            IStatusMessage(self.request).add(_(u"Theme disabled."))
            self._setup()
            return True

        if 'form.button.AdvancedSave' in form:
            self.authorize()

            self.theme_settings.readNetwork = form.get('readNetwork', False)

            themeEnabled = form.get('themeEnabled', False)
            rules = form.get('rules', None)
            prefix = form.get('absolutePrefix', None)
            doctype = str(form.get('doctype', ""))

            hostnameBlacklist = form.get('hostnameBlacklist', [])

            parameterExpressions = {}
            parameterExpressionsList = form.get('parameterExpressions', [])

            for line in parameterExpressionsList:
                try:
                    name, expression = line.split('=', 1)
                    name = str(name.strip())
                    expression = str(expression.strip())
                    parameterExpressions[name] = expression
                except ValueError:
                    message = _(
                        'error_invalid_parameter_expressions',
                        default=u"Please ensure you enter one expression per "
                        u"line, in the format <name> = <expression>.")
                    self.errors['parameterExpressions'] = message

            themeBase = form.get('themeBase', None)
            markSpecialLinks = form.get('markSpecialLinks', None)
            extLinksOpenInNewWindow = form.get('extLinksOpenInNewWindow', None)

            if not self.errors:
                # Trigger onDisabled() on plugins if theme was active
                # previously and rules were changed
                if self.theme_settings.rules != rules:
                    applyTheme(None)

                self.theme_settings.enabled = themeEnabled
                self.theme_settings.rules = rules
                self.theme_settings.absolutePrefix = prefix
                self.theme_settings.parameterExpressions = parameterExpressions
                self.theme_settings.hostnameBlacklist = hostnameBlacklist
                self.theme_settings.doctype = doctype

                # Theme base settings
                if themeBase is not None:
                    self.pskin.default_skin = themeBase.encode('utf-8')
                if markSpecialLinks is not None:
                    self.mark_special_links = markSpecialLinks
                if extLinksOpenInNewWindow is not None:
                    self.ext_links_open_new_window = extLinksOpenInNewWindow

                IStatusMessage(self.request).add(_(u"Changes saved"))
                self._setup()
                return True
            else:
                IStatusMessage(self.request).add(_(u"There were errors"),
                                                 'error')
                self.redirectToFieldset('advanced')
                return False

        if 'form.button.Import' in form:
            self.authorize()

            enableNewTheme = form.get('enableNewTheme', False)
            replaceExisting = form.get('replaceExisting', False)
            themeArchive = form.get('themeArchive', None)

            themeZip = None
            performImport = False

            try:
                themeZip = zipfile.ZipFile(themeArchive)
            except (
                    zipfile.BadZipfile,
                    zipfile.LargeZipFile,
            ):
                logger.exception("Could not read zip file")
                self.errors['themeArchive'] = _(
                    'error_invalid_zip',
                    default=u"The uploaded file is not a valid Zip archive")

            if themeZip:

                try:
                    themeData = extractThemeInfo(themeZip, checkRules=False)
                except (
                        ValueError,
                        KeyError,
                ), e:
                    logger.warn(str(e))
                    self.errors['themeArchive'] = _(
                        'error_no_rules_file',
                        u"The uploaded file does not contain a valid theme "
                        u"archive.")
                else:

                    themeContainer = getOrCreatePersistentResourceDirectory()
                    themeExists = themeData.__name__ in themeContainer

                    if themeExists:
                        if not replaceExisting:
                            self.errors['themeArchive'] = _(
                                'error_already_installed',
                                u"This theme is already installed. Select "
                                u"'Replace existing theme' and re-upload to "
                                u"replace it.")
                        else:
                            del themeContainer[themeData.__name__]
                            performImport = True
                    else:
                        performImport = True

            if performImport:
                themeContainer.importZip(themeZip)

                themeDirectory = queryResourceDirectory(
                    THEME_RESOURCE_NAME, themeData.__name__)
                if themeDirectory is not None:
                    # If we don't have a rules file, use the template
                    if themeData.rules == u"/++{0:s}++{1:s}/{2:s}".format(
                            THEME_RESOURCE_NAME,
                            themeData.__name__,
                            RULE_FILENAME,
                    ) and not themeDirectory.isFile(RULE_FILENAME):
                        templateThemeDirectory = queryResourceDirectory(
                            THEME_RESOURCE_NAME, TEMPLATE_THEME)
                        themeDirectory.writeFile(
                            RULE_FILENAME,
                            templateThemeDirectory.readFile(RULE_FILENAME))

                        if not themeDirectory.isFile(DEFAULT_THEME_FILENAME):
                            IStatusMessage(self.request).add(
                                _(u"A boilerplate rules.xml was added to "
                                  u"your theme, but no index.html file "
                                  u"found. Update rules.xml to reference "
                                  u"the current theme file."),
                                'warning',
                            )

                    plugins = getPlugins()
                    pluginSettings = getPluginSettings(themeDirectory, plugins)
                    if pluginSettings is not None:
                        for name, plugin in plugins:
                            plugin.onCreated(themeData.__name__,
                                             pluginSettings[name],
                                             pluginSettings)

                if enableNewTheme:
                    applyTheme(themeData)
                    self.theme_settings.enabled = True

            if not self.errors:
                self.redirect(
                    "{0}/++theme++{1}/@@theming-controlpanel-mapper".format(
                        self.site_url, themeData.__name__))
                return False
            else:
                IStatusMessage(self.request).add(_(u"There were errors"),
                                                 "error")

                self.renderOverlay('upload')
                return True

        if 'form.button.CreateTheme' in form:
            self.authorize()

            title = form.get('title')
            description = form.get('description') or ''
            baseOn = form.get('baseOn', TEMPLATE_THEME)
            enableImmediately = form.get('enableImmediately', True)

            if not title:
                self.errors['title'] = _(u"Title is required")

                IStatusMessage(self.request).add(_(u"There were errors"),
                                                 'error')

                self.renderOverlay('new-theme')
                return True

            else:

                if any(x.__name__ == title for x in getZODBThemes()):
                    self.errors['title'] = _(u"Duplicate title")

                    IStatusMessage(self.request).add(
                        _(u"This title is already in use"), 'error')

                    return True

                name = createThemeFromTemplate(title, description, baseOn)
                self._setup()

                if enableImmediately:
                    themeData = self.getThemeData(self.availableThemes, name)
                    applyTheme(themeData)
                    self.theme_settings.enabled = True

                self.redirect(
                    "{0}/++theme++{1}/@@theming-controlpanel-mapper".format(
                        self.site_url, name))
                return False

        if 'form.button.DeleteSelected' in form:
            self.authorize()

            toDelete = form.get('themes', [])
            themeDirectory = getOrCreatePersistentResourceDirectory()

            for theme in toDelete:
                del themeDirectory[theme]

            IStatusMessage(self.request).add(_(u"Theme deleted"), 'info')

            self._setup()
            return True

        return True
Exemplo n.º 45
0
 def cancel(self, action):
     IStatusMessage(self.request).addStatusMessage(_("Changes canceled."),
                                                   type="info")
     self.request.response.redirect(
         '%s%s' % (self.request['ACTUAL_URL'], self.makeQuery()))
Exemplo n.º 46
0
    def handle_send(self, action):
        self.portal_state = getMultiAdapter((self.context, self.request),
                                            name=u'plone_portal_state')

        self.portal = self.portal_state.portal()
        self.membership_tool = getToolByName(self.context, 'portal_membership')

        self.feedback_template = self.context.restrictedTraverse(
            '@@author-feedback-template')

        data, errors = self.extractData()
        if errors:
            IStatusMessage(self.request).addStatusMessage(
                self.formErrorsMessage, type=u'error')

            return

        referer = data.get('referer', 'unknown referer')
        subject = data.get('subject', '')
        message = data.get('message', '')
        # Author is None means portal administrator
        author = data.get('author', None)

        sender = self.portal_state.member()
        registry = getUtility(IRegistry)
        mail_settings = registry.forInterface(IMailSchema, prefix='plone')
        envelope_from = mail_settings.email_from_address

        if author is None:
            send_to_address = mail_settings.email_from_address
        else:
            author_member = self.membership_tool.getMemberById(author)
            send_to_address = author_member.getProperty('email')

        send_from_address = sender.getProperty('email')

        if send_from_address == '':
            IStatusMessage(self.request).addStatusMessage(
                _(u'Could not find a valid email address'), type=u'error')
            return

        sender_id = "%s (%s), %s" % (sender.getProperty('fullname'),
                                     sender.getId(), send_from_address)

        mail_host = getUtility(IMailHost)
        registry = getUtility(IRegistry)
        email_charset = registry.get('plone.email_charset', 'utf-8')

        try:
            message = self.feedback_template(
                self,
                send_from_address=send_from_address,
                sender_id=sender_id,
                url=referer,
                subject=subject,
                message=message,
                encoding=email_charset,
                email_from_name=mail_settings.email_from_name)

            message = message.encode(email_charset)

            mail_host.send(message,
                           send_to_address,
                           envelope_from,
                           subject=subject,
                           charset=email_charset)
        except ConflictError:
            raise
        except Exception as e:
            logger.info("Unable to send mail: " + str(e))

            IStatusMessage(self.request).addStatusMessage(
                _(u'Unable to send mail.'), type=u'error')

            return

        IStatusMessage(self.request).addStatusMessage(_(u'Mail sent.'),
                                                      type=u'info')
        self.request.response.redirect(
            '%s/author/%s' % (self.portal.absolute_url(), author or ''))
        return
Exemplo n.º 47
0
    def handleApply(self, action):
        portal = getSite()
        pm = getToolByName(portal, 'portal_membership')
        lt = getToolByName(portal, 'portal_languages')

        userid = pm.getAuthenticatedMember()

        user_email = userid.getProperty('email', '')

        if not user_email:
            IStatusMessage(self.request).addStatusMessage(
                _(u'La reunió no es pot crear perquè l\'usuari no te informat la adreca de correu electrònic.'
                  ), u'error')
            self.request.response.redirect(portal.absolute_url())

        data, errors = self.extractData()
        if errors:
            self.status = self.formErrorsMessage
            return

        str_start_date = data.get('start_date').isoformat().replace('T',
                                                                    '-')[:-6]
        str_invitats_convidats = data.get('invitats_convidats',
                                          '').replace(' ', '')

        # Guard because the invitats_espectadors field is not required
        if data.get('invitats_espectadors', False):
            str_invitats_espectadors = data.get('invitats_espectadors',
                                                '').replace(' ', '')
        else:
            str_invitats_espectadors = ''

        guests = data.get('invitats_convidats')
        session_load = len(guests.split(','))

        payload = dict(servidor=BBB_SERVER,
                       inici=str_start_date,
                       durada=data.get('durada'),
                       carrega=session_load,
                       descripcio=data.get('nom_reunio'),
                       owner=user_email,
                       invite_rw=str_invitats_convidats,
                       invite_ro=str_invitats_espectadors,
                       lang=lt.getDefaultLanguage())

        req = requests.post(BBB_ENDPOINT, data=payload)

        try:
            # Redirect back to the front page with a status message
            if int(req.text) > 0:
                IStatusMessage(self.request).addStatusMessage(
                    _(u'La reunió virtual ha estat creada.'), u'info')
            else:
                IStatusMessage(self.request).addStatusMessage(
                    _(u'Hi ha hagut algun problema i la reunió virtual no ha estat creada.'
                      ), u'info')
        except:
            IStatusMessage(self.request).addStatusMessage(
                _(u'Hi ha hagut algun problema i la reunió virtual no ha estat creada.'
                  ), u'info')

        self.request.response.redirect(portal.absolute_url())
Exemplo n.º 48
0
 def actionMigrate(self, action, data):
     output = migrateMonetEvent(self.context)
     IStatusMessage(self.request).addStatusMessage(output, type='info')
     return self.request.response.redirect(self.context.absolute_url())
Exemplo n.º 49
0
 def handleCancel(self, action):
     IStatusMessage(self.request).addStatusMessage(_(u"Changes canceled."),
                                                   "info")
     self.request.response.redirect(
         "%s/%s" % (self.context.absolute_url(), self.control_panel_view))
Exemplo n.º 50
0
 def cancel(self, action):
     IStatusMessage(self.request).addStatusMessage(_(u'Edit cancelled.'),
                                                   type='info')
     self.request.response.redirect(self.context.absolute_url())
     return ''
Exemplo n.º 51
0
                fullname = row[0] + ' ' + row[1]
                username = self.sanitize(fullname.lower().replace(' ', '-'))
                properties['username'] = username
                properties['fullname'] = fullname
                try:
                    # addMember() returns MemberData object
                    member = regtool.addMember(username, 'secret', properties=properties)
                except ValueError, e:
                    # Give user visual feedback what went wrong
                    IStatusMessage(self.request).add(_(u"Could not create the users. %s" % username) + unicode(e), "error")
                    continue
                else:
                    log.info('Registered dummy user: %s' % fullname)
            row_num += 1

        IStatusMessage(self.request).add(_(u"Succesfully created %d users." % (row_num-1)), "info")
        return self.request.RESPONSE.redirect('/'.join(self.context.getPhysicalPath()))

    def sanitize(self, str):
        for code, ascii in [('\xc3\xbc', 'ue'),
                            ('\xc3\xb6', 'oe'),
                            ('\xc3\xa4', 'ae'),
                            ('\xc3\xa7', 'c'),
                            ('\xc3\xa8', 'e'),
                            ('\xc3\xa9', 'e'),
                            ('\xc3\xab', 'e'),
                            ('\xc3\xaf', 'i'),
                            ('\xc5\x9e', 'S'),
                            ('\xc5\x9f', 'e'),
                            ]:
            str = str.replace(code, ascii)
Exemplo n.º 52
0
    def handleComment(self, action):
        context = aq_inner(self.context)

        # Check if conversation is enabled on this content object
        if not self.__parent__.restrictedTraverse(
                '@@conversation_view').enabled():
            raise Unauthorized("Discussion is not enabled for this content "
                               "object.")

        # Validation form
        data, errors = self.extractData()
        if errors:
            return

        # Validate Captcha
        registry = queryUtility(IRegistry)
        settings = registry.forInterface(IDiscussionSettings, check=False)
        portal_membership = getToolByName(self.context, 'portal_membership')
        captcha_enabled = settings.captcha != 'disabled'
        anonymous_comments = settings.anonymous_comments
        anon = portal_membership.isAnonymousUser()
        if captcha_enabled and anonymous_comments and anon:
            if not 'captcha' in data:
                data['captcha'] = u""
            captcha = CaptchaValidator(self.context, self.request, None,
                                       ICaptcha['captcha'], None)
            captcha.validate(data['captcha'])

        # some attributes are not always set
        author_name = u""

        # Create comment
        comment = createObject('plone.Comment')

        # Set comment mime type to current setting in the discussion registry
        comment.mime_type = settings.text_transform

        # Set comment attributes (including extended comment form attributes)
        for attribute in self.fields.keys():
            setattr(comment, attribute, data[attribute])
        # Make sure author_name is properly encoded
        if 'author_name' in data:
            author_name = data['author_name']
            if isinstance(author_name, str):
                author_name = unicode(author_name, 'utf-8')

        # Set comment author properties for anonymous users or members
        can_reply = getSecurityManager().checkPermission(
            'Reply to item', context)
        portal_membership = getToolByName(self.context, 'portal_membership')
        if anon and anonymous_comments:
            # Anonymous Users
            comment.author_name = author_name
            comment.author_email = u""
            comment.user_notification = None
            comment.creation_date = datetime.utcnow()
            comment.modification_date = datetime.utcnow()
        elif not portal_membership.isAnonymousUser() and can_reply:
            # Member
            member = portal_membership.getAuthenticatedMember()
            username = member.getUserName()
            email = member.getProperty('email')
            fullname = member.getProperty('fullname')
            if not fullname or fullname == '':
                fullname = member.getUserName()
            # memberdata is stored as utf-8 encoded strings
            elif isinstance(fullname, str):
                fullname = unicode(fullname, 'utf-8')
            if email and isinstance(email, str):
                email = unicode(email, 'utf-8')
            comment.creator = username
            comment.author_username = username
            comment.author_name = fullname
            comment.author_email = email
            comment.creation_date = datetime.utcnow()
            comment.modification_date = datetime.utcnow()
        else:  # pragma: no cover
            raise Unauthorized(
                u"Anonymous user tries to post a comment, but anonymous "
                u"commenting is disabled. Or user does not have the "
                u"'reply to item' permission.")

        # Add comment to conversation
        conversation = IConversation(self.__parent__)
        if data['in_reply_to']:
            # Add a reply to an existing comment
            conversation_to_reply_to = conversation.get(data['in_reply_to'])
            replies = IReplies(conversation_to_reply_to)
            comment_id = replies.addComment(comment)
        else:
            # Add a comment to the conversation
            comment_id = conversation.addComment(comment)

        # Redirect after form submit:
        # If a user posts a comment and moderation is enabled, a message is
        # shown to the user that his/her comment awaits moderation. If the user
        # has 'review comments' permission, he/she is redirected directly
        # to the comment.
        can_review = getSecurityManager().checkPermission(
            'Review comments', context)
        workflowTool = getToolByName(context, 'portal_workflow')
        comment_review_state = workflowTool.getInfoFor(comment, 'review_state',
                                                       None)
        if comment_review_state == 'pending' and not can_review:
            # Show info message when comment moderation is enabled
            IStatusMessage(self.context.REQUEST).addStatusMessage(
                _("Your comment awaits moderator approval."), type="info")
            self.request.response.redirect(self.action)
        else:
            # Redirect to comment (inside a content object page)
            self.request.response.redirect(self.action + '#' + str(comment_id))
Exemplo n.º 53
0
def addStatusMessage(request, message, type='info'):
    """Add a status message to the request.
    """
    IStatusMessage(request).addStatusMessage(message, type=type)
Exemplo n.º 54
0
    def __call__(self):
        state = self.request.form.get('state')
        messages = IStatusMessage(self.request)
        translator = self.context.translate
        navigation_root = api.portal.get_navigation_root(context=self.context)
        if 'error' in self.request.form:
            messages = IStatusMessage(self.request)
            reason = self.request.form.get('error')

            # noinspection PyArgumentList
            messages.add(translator(
                _(u'message_%s_failed' % state, mapping={u'reason':
                                                         reason}), ),
                         type='error')

            self.request.response.redirect(navigation_root.absolute_url() +
                                           '/@@id4me')
            return

        if 'code' not in self.request.form:
            raise BadRequest('no code given')

        code = self.request.form.get('code')

        if state == 'login':
            user = self.auth_util.verify_user_login(code)
            if user:
                acl_users = getToolByName(self.context, 'acl_users')

                # noinspection PyProtectedMember
                acl_users.session._setupSession(user.getId(),
                                                self.request.response)

                # noinspection PyArgumentList
                messages.add(translator(_(u'message_login_successful')),
                             type='info')

                self.request.response.redirect(navigation_root.absolute_url())
            else:
                # noinspection PyArgumentList
                messages.add(translator(_(u'message_no_user_connected')),
                             type='error')

                self.request.response.redirect(navigation_root.absolute_url() +
                                               '/@@id4me')
        elif state == 'register':
            if not api.portal.get_registry_record(
                    name='plone.enable_self_reg'):
                raise Forbidden()

            user = self.auth_util.register_user(code)

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

            # noinspection PyProtectedMember
            acl_users.session._setupSession(user.getId(),
                                            self.request.response)

            # noinspection PyArgumentList
            messages.add(translator(
                _(u'message_account_created',
                  mapping={u'user_id': user.getId()})),
                         type='info')

            self.request.response.redirect(navigation_root.absolute_url())
        elif state == 'connect':
            if api.user.is_anonymous():
                raise Forbidden('No user logged in')
            user = api.user.get_current()

            self.auth_util.connect_user_login(user=user, code=code)

            # noinspection PyArgumentList
            messages.add(
                translator(
                    _(
                        u'message_login_connected',
                        # ToDo: get Identity Agent information
                        mapping={u'agent': 'NOT_FOUND'})),
                type='info')

            self.request.response.redirect(navigation_root.absolute_url())
        else:
            # ToDo: handle Case
            raise BadRequest('no state given')
Exemplo n.º 55
0
 def handleCancel(self, action):
     IStatusMessage(self.request).addStatusMessage(_(u'Edit cancelled'),
                                                   'info')
     self.request.response.redirect('{context_url}/{view}'.format(
         context_url=self.context.absolute_url(),
         view="@@overview-controlpanel"))
Exemplo n.º 56
0
 def redirect(self, message):
     IStatusMessage(self.request).add(message)
     self.request.response.redirect("{0:s}/@@theming-controlpanel".format(
         self.portalUrl))
Exemplo n.º 57
0
    def extract_attachments(self, positions, delete_action):
        dossier = self.find_parent_dossier()

        attachments_to_extract = filter(
            lambda att: att.get('position') in positions,
            get_attachments(self.context.msg))

        # create documents from the selected attachments
        for att in attachments_to_extract:
            pos = att.get('position')
            filename = att.get('filename')

            # remove line breaks from the filename
            filename = re.sub('\s{1,}', ' ', filename)

            kwargs = {
                'title': filename[:filename.rfind('.')].decode('utf-8'),
                'file': self.get_attachment_as_namedfile(pos),
                'keywords': (),
                'digitally_available': True
            }

            doc = createContentInContainer(dossier,
                                           'opengever.document.document',
                                           **kwargs)

            for schemata in iterSchemata(doc):
                for name, field in getFieldsInOrder(schemata):
                    if name not in kwargs.keys():
                        default = queryMultiAdapter(
                            (
                                doc,
                                doc.REQUEST,  # request
                                None,  # form
                                field,
                                None,  # Widget
                            ),
                            IValue,
                            name='default')
                        if default is not None:
                            default = default.get()
                        if default is None:
                            default = getattr(field, 'default', None)
                        if default is None:
                            try:
                                default = field.missing_value
                            except:
                                pass
                        field.set(field.interface(doc), default)

            # add a reference from the attachment to the mail
            intids = getUtility(IIntIds)
            iid = intids.getId(self.context)

            # prevent circular dependencies
            from opengever.document.behaviors import IRelatedDocuments
            IRelatedDocuments(doc).relatedItems = [RelationValue(iid)]

            msg = _(u'info_extracted_document',
                    default=u'Created document ${title}',
                    mapping={'title': doc.Title().decode('utf-8')})
            IStatusMessage(self.request).addStatusMessage(msg, type='info')

            # reindex the new document to index also all the default values
            doc.reindexObject()

        # delete the attachments from the email message, if needed
        if delete_action in ('all', 'selected'):
            if delete_action == 'selected':
                pos_to_delete = positions
            else:
                # all
                pos_to_delete = [
                    int(att['position'])
                    for att in get_attachments(self.context.msg)
                ]

            # set the new message file
            msg = remove_attachments(self.context.msg, pos_to_delete)
            self.context.message = NamedFile(
                data=msg.as_string(),
                contentType=self.context.message.contentType,
                filename=self.context.message.filename)
Exemplo n.º 58
0
    def handleSubmit(self, action):
        """
        Here we should check couple of things:

        - If the token provided is valid.
        - If the signature contains the user data needed (username and hash made of his data are valid).

        If all is well and valid, we sudo login the user given.
        """
        if not action.title == _(u'Verify'):
            return

        logger.debug('verify')

        data, errors = self.extractData()
        if errors:
            return False

        token = data.get('token', '')

        if not token:
            IStatusMessage(self.request).addStatusMessage(
                _("No token provided!"), 'error')
            return

        user = None
        username = self.request.get('auth_user', '')

        if username:
            user = api.user.get(username=username)

            # Validating the signed request data. If invalid (likely throttled with or expired), generate an
            # appropriate error message.
            user_data_validation_result = validate_user_data(
                request=self.request, user=user)
            if not user_data_validation_result.result:
                if 'Signature timestamp expired!' in user_data_validation_result.reason:
                    # Remove used authentication code
                    user.setMemberProperties(
                        mapping={
                            'mobile_number_authentication_code': '',
                        })
                IStatusMessage(self.request).addStatusMessage(
                    _("Invalid data. Details: {0}").format(' '.join(
                        user_data_validation_result.reason)), 'error')
                return

        valid_token = validate_mobile_number_authentication_code(token,
                                                                 user=user)

        if valid_token:
            # We should login the user here
            self.context.acl_users.session._setupSession(
                str(username), self.context.REQUEST.RESPONSE)

            mapping = {
                'mobile_number_authentication_code': '',
            }
            mapping.update(get_updated_ips_for_member_properties_update(user))

            # Remove used authentication code and update the IPs list
            user.setMemberProperties(mapping=mapping)

            # TODO: Is there a nicer way of resolving the "@@sms_authenticator_token_form" URL?
            IStatusMessage(self.request).addStatusMessage(
                __("Welcome! You are now logged in."), 'info')
            request_data = extract_request_data(self.request)
            redirect_url = request_data.get('next_url',
                                            self.context.absolute_url())
            self.request.response.redirect(redirect_url)
        else:
            IStatusMessage(self.request).addStatusMessage(
                _("Invalid token or token expired."), 'error')
Exemplo n.º 59
0
    def handleSubmit(self, action):
        data, errors = self.extractData()
        if errors:
            return False

        username = data.get('username', '')
        mobile_number = data.get('mobile_number', '')

        user = api.user.get(username=username)

        reason = None
        if user:
            try:
                # Here we need to generate a token which is valid for let's say, 2 hours
                # using which it should be possible to reset the mobile number. The `signature`
                # generated should be saved in the user profile `mobile_number_reset_token`.
                ska_secret_key = get_ska_secret_key(request=self.request,
                                                    user=user)

                # We also need to generate another token (no security, just a random string)
                # to sent to users' mobile number.
                mobile_number_reset_code = generate_code(user)

                token_lifetime = get_ska_token_lifetime()

                signature = Signature.generate_signature(
                    auth_user=username,
                    secret_key=ska_secret_key,
                    lifetime=token_lifetime,
                    extra={'mobile_number': mobile_number})

                request_helper = RequestHelper(signature_param='signature',
                                               auth_user_param='auth_user',
                                               valid_until_param='valid_until')

                signed_url = request_helper.signature_to_url(
                    signature=signature,
                    endpoint_url='{0}/{1}'.format(self.context.absolute_url(),
                                                  '@@reset-mobile-number'))

                # Send the SMS
                sms_sent = send_mobile_number_reset_confirmation_code_sms(
                    mobile_number=mobile_number, code=mobile_number_reset_code)

                if not sms_sent:
                    IStatusMessage(self.request).addStatusMessage(
                        _("An error occured while sending the SMS to the number specified."
                          ), 'info')
                    redirect_url = "{0}".format(self.context.absolute_url())
                    self.request.response.redirect(redirect_url)
                    return

                # Save the `signature` value to the `mobile_number_reset_token`.
                user.setMemberProperties(
                    mapping={
                        'mobile_number_reset_token': str(signature),
                        'mobile_number_reset_code': mobile_number_reset_code,
                        'mobile_number_authentication_code': '',
                    })

                # Now we need to send an email to user with URL in and a small explanations.
                try:
                    host = getToolByName(self, 'MailHost')

                    mail_text_template = self.context.restrictedTraverse(
                        'request_mobile_number_reset_email')
                    mail_text = mail_text_template(
                        member=user,
                        mobile_number_reset_url=signed_url,
                        charset='utf-8')
                    mail_text = mail_text.format(
                        mobile_number_reset_url=signed_url)

                    host.send(mail_text.encode('UTF-8'),
                              immediate=True,
                              msg_type='text/html')
                except SMTPRecipientsRefused as e:
                    raise SMTPRecipientsRefused(
                        'Recipient address rejected by server')

                IStatusMessage(self.request).addStatusMessage(
                    _("An email with further instructions for (re)setting your mobile number has been sent."
                      ), 'info')
                redirect_url = "{0}/@@reset-email-sent".format(
                    self.context.absolute_url())
                self.request.response.redirect(redirect_url)
            except ValueError as e:
                reason = _(str(e))
        else:
            reason = _("Invalid username.")

        if reason is not None:
            IStatusMessage(self.request).addStatusMessage(
                _("Request for mobile number reset is failed! {0}").format(
                    reason), 'error')
Exemplo n.º 60
0
 def update(self):
     messages = IStatusMessage(self.request).show()
     for message in messages:
         message.type = self.mapping.get(message.type, message.type)
     self.messages = messages