Esempio n. 1
0
 def evaluate_path(self, req, parts):
     if len(parts) < 2:
         raise PathDontMatch()
     # remove last part and see if this is something like an actions
     # if so, call
     # XXX bad smell: refactor to simpler code
     try:
         actionsreg = self.vreg['actions']
         requested = parts.pop(-1)
         actions = actionsreg[requested]
     except RegistryException:
         raise PathDontMatch()
     for evaluator in self.urlpublisher.evaluators:
         if evaluator is self or evaluator.priority == 0:
             continue
         try:
             pmid, rset = evaluator.evaluate_path(req, parts[:])
         except PathDontMatch:
             continue
         else:
             try:
                 action = actionsreg._select_best(actions, req, rset=rset)
                 if action is not None:
                     raise Redirect(action.url())
             except RegistryException:
                 pass  # continue searching
     raise PathDontMatch()
Esempio n. 2
0
class RegistrationConfirmController(controller.Controller):
    """ Create the CWUser when user confirm the account creation by clicking
    the link of the confirmation mail.
    """
    __regid__ = "registration_confirm"

    def publish(self, rset=None):
        req = self._cw
        try:
            data = crypto.decrypt(req.form["key"],
                                  self._cw.vreg.config._secret)
            login = data["login"]
            password = data.pop("upassword")
        except:
            msg = req._(
                u"Invalid registration data. Please try registering again.")
            raise Redirect(req.build_url("register", _message=msg))
        if self._cw.user.login == login:
            # already logged in (e.g. regstration link replayed twice in the browser)
            raise Redirect(self.success_redirect_url(self._cw.user.name()))
        # Check the user has not been created yet
        with self.appli.repo.internal_cnx() as cnx:
            msg = req._(u"Account already validated. Please try to login.")
            rset = cnx.execute(
                "Any U Where U is CWUser, U login '{0}'".format(login))
        if rset.rowcount != 0:
            raise Redirect(req.build_url("register", _message=msg))
        req.form = data  # hijack for proper validation error handling
        err_raised = False
        try:
            with self.appli.repo.internal_cnx() as cnx:
                cnx.call_service("register_user",
                                 login=unicode(login),
                                 password=password,
                                 email=unicode(data.get("mail")),
                                 firstname=unicode(data.get("firstname")),
                                 surname=unicode(data.get("surname")))
                cnx.commit()
        except ValidationError, err:
            err_raised = True
            # XXX TEMPORARY HACK to allow registration links to work more than
            # once. This is required because some email clients (e.g. kmail)
            # start by downloading the url to find the mimetype of the resource
            # and then execute the appropriate action (e.g. open the url in the
            # default browser) based on the mimetype.
            if err.errors.keys() != ["login"]:
                raise
        # Try to connect using the provided credentials
        try:
            from cubicweb import repoapi
            cnx = repoapi.connect(self.appli.repo, login, password=password)
            with cnx:
                name = cnx.user.name()
            raise Redirect(self.success_redirect_url(name))
        except:
            if err_raised:
                # Both registration and login failed, re-raise the previous
                # ValidationError
                raise err
            raise
Esempio n. 3
0
 def publish(self, rset=None):
     job_id = self._cw.form['condor_job_id']
     schedd_name = self._cw.form['condor_schedd_name']
     errcode, output = remove(self._cw.vreg.config, schedd_name, job_id)
     raise Redirect(
         self._cw.build_url(vid='condor_jobs',
                            __message=xml_escape(output.strip())))
Esempio n. 4
0
 def publish(self, rset=None):
     sessionid = self._cw.session.sessionid
     if sessionid not in self.appli.repo._piws_expired_sessionids:
         self.appli.repo._piws_expired_sessionids.add(sessionid)
         self.appli.repo.info(
             'session {0} has logged out'.format(sessionid))
     raise Redirect(self._cw.base_url())
Esempio n. 5
0
 def entity_call(self, entity):
     import_log_eid = self._cw.call_service('source-sync',
                                            source_eid=entity.eid)
     msg = self._cw._(
         'Synchronization has been requested, refresh this page in a few '
         'minutes.')
     import_log = self._cw.entity_from_eid(import_log_eid)
     url = import_log.absolute_url(__message=msg)
     raise Redirect(url)
Esempio n. 6
0
 def sendmail(self, recipient, subject, body):
     senderemail = self._cw.user.cw_adapt_to('IEmailable').get_email()
     msg = format_mail(
         {
             'email': senderemail,
             'name': self._cw.user.dc_title(),
         }, [recipient], body, subject)
     if not self._cw.vreg.config.sendmails([(msg, [recipient])]):
         msg = self._cw._('could not connect to the SMTP server')
         url = self._cw.build_url(__message=msg)
         raise Redirect(url)
Esempio n. 7
0
 def publish(self, rset=None):
     req = self._cw
     desc = req.form['description']
     # The description is generated and signed by cubicweb itself, check
     # description's signature so we don't want to send spam here
     sign = req.form.get('__signature', '')
     if not (sign and req.vreg.config.check_text_sign(desc, sign)):
         raise Forbidden('Invalid content')
     self.sendmail(req.vreg.config['submit-mail'],
                   req._('%s error report') % req.vreg.config.appid, desc)
     raise Redirect(req.build_url(__message=req._('bug report sent')))
Esempio n. 8
0
 def publish(self, rset=None):
     req = self._cw
     if (req._headers_in.getRawHeaders('x-requested-with') == [
             'XMLHttpRequest'
     ]):
         session_handler = self.appli.session_handler
         session_handler.session_manager.close_session(req.session)
         req.remove_cookie(session_handler.session_cookie(req))
         # Will raise a proper AuthenticationError
         raise LogOut()
     else:
         # Redirect unauthorised attempts to close the session to the logout
         # controller
         raise Redirect(self._cw.base_url() + 'logout')
Esempio n. 9
0
 def _redirect(self, newparams):
     """Raise a redirect. We use __redirectpath if it specified, else we
     return to the home page.
     """
     if '__redirectpath' in self._cw.form:
         # if redirect path was explicitly specified in the form, use it
         path = self._cw.form['__redirectpath']
         url = self._cw.build_url(path)
         url = append_url_params(url, self._cw.form.get('__redirectparams'))
     else:
         url = self._cw.base_url()
     # The newparams must update the params in all cases
     url = self._cw.rebuild_url(url, **newparams)
     raise Redirect(url)
Esempio n. 10
0
    def publish(self, rset=None):
        """ Publish the form data.

        You will have to specify the SMTP host in the instance
        all-in-one.conf file:

            smtp-host=mx.intra.cea.fr
        """
        # Check the form content
        data = self.checked_data()

        # Send a confirmation email
        recipient = data["mail"]
        msg = self.build_email(recipient, data)
        self._cw.vreg.config.sendmails([(msg, (recipient, ))])

        # Redirection
        raise Redirect(self.success_redirect_url())
Esempio n. 11
0
 def _return_to_original_view(self, newparams):
     """validate-button case"""
     # transforms __redirect[*] parameters into regular form parameters
     newparams.update(redirect_params(self._cw.form))
     # find out if we have some explicit `rql` needs
     rql = newparams.pop('rql', None)
     # if rql is needed (explicit __redirectrql or multiple deletions for
     # instance), we have to use the old `view?rql=...` form
     if rql:
         path = 'view'
         newparams['rql'] = rql
     elif '__redirectpath' in self._cw.form:
         # if redirect path was explicitly specified in the form, use it
         path = self._cw.form['__redirectpath']
         if (self._edited_entity
                 and path != self._edited_entity.rest_path()
                 and '_cwmsgid' in newparams):
             # are we here on creation or modification?
             if any(eid == self._edited_entity.eid
                    for eid in self._cw.data.get('eidmap', {}).values()):
                 msg = self._cw._('click here to see created entity')
             else:
                 msg = self._cw._('click here to see edited entity')
             msg = u'(<a href="%s">%s</a>)' % (xml_escape(
                 self._edited_entity.absolute_url()), msg)
             self._cw.append_to_redirect_message(msg)
     elif self._after_deletion_path:
         # else it should have been set during form processing
         path, params = self._after_deletion_path
         params = dict(params)  # params given as tuple
         params.update(newparams)
         newparams = params
     elif self._edited_entity:
         # clear caches in case some attribute participating to the rest path
         # has been modified
         self._edited_entity.cw_clear_all_caches()
         path = self._edited_entity.rest_path()
     else:
         path = 'view'
     url = self._cw.build_url(path, **newparams)
     url = append_url_params(url, self._cw.form.get('__redirectparams'))
     raise Redirect(url)
Esempio n. 12
0
 def _return_to_edition_view(self, newparams):
     """apply-button case"""
     form = self._cw.form
     if self._edited_entity:
         path = self._edited_entity.rest_path()
         newparams.pop('rql', None)
     # else, fallback on the old `view?rql=...` url form
     elif 'rql' in self._cw.form:
         path = 'view'
         newparams['rql'] = form['rql']
     else:
         self.warning('the edited data seems inconsistent')
         path = 'view'
     # pick up the correction edition view
     if form.get('__form_id'):
         newparams['vid'] = form['__form_id']
     # re-insert copy redirection parameters
     for redirectparam in NAV_FORM_PARAMETERS:
         if redirectparam in form:
             newparams[redirectparam] = form[redirectparam]
     raise Redirect(self._cw.build_url(path, **newparams))
Esempio n. 13
0
 def publish(self, rset=None):
     session = self._cw.session
     sessionid = session.sessionid
     session.repo.info('session {0} logged out'.format(sessionid))
     if hasattr(session.repo, "_expired_sessionids"):
         self._cw.session.repo._expired_sessionids[sessionid] = True
         raise Redirect(self._cw.base_url())
     else:
         html = "<!DOCTYPE html>"
         html += "<html lang='en'>"
         html += "<head>"
         html += "<meta charset='utf-8'>"
         html += "<title>Loading</title>"
         html += ("<script src='//code.jquery.com/"
                  "jquery-1.11.3.min.js'></script>")
         html += "</head>"
         html += "<body>"
         html += "<script>"
         html += "$(document).ready(function() {"
         # Ajax callback to flush browser Apache http credentials
         html += "$.ajax({"
         html += "url: 'index.php',"
         html += "async: false,"
         html += "username: '******',"
         html += "password: '******'"
         # Last step : redirection to the specified url
         html += "}).fail(function() {"
         html += "window.location.replace('{0}');".format(
             self._cw.vreg.config["deauth-redirect-url"])
         html += "});"
         html += "});"
         html += "</script>"
         # Warning diplayed if Javascript s disabled
         html += "<noscript>"
         html += ("Javascript is not activated. Please activate "
                  "javascript and restart your web-browser.")
         html += "</noscript>"
         html += "</body>"
         html += "</html>"
         return "{0}".format(html)
Esempio n. 14
0
 def publish(self, rset=None):
     config = self._cw.vreg.config
     # includeparams=True for modconcat-like urls
     relpath = self.relpath
     if relpath.startswith(self.data_modconcat_basepath):
         paths = relpath[len(self.data_modconcat_basepath):].split(',')
         filepath = self.concat_files_registry.concat_cached_filepath(paths)
     else:
         if not relpath.startswith(self.base_datapath):
             # /data/foo, redirect to /data/{hash}/foo
             prefix = 'data/'
             relpath = relpath[len(prefix):]
             raise Redirect(self._cw.data_url(relpath), 302)
         # skip leading '/data/{hash}/' and url params
         prefix = self.base_datapath
         relpath = relpath[len(prefix):]
         relpath = relpath.split('?', 1)[0]
         dirpath, rid = config.locate_resource(relpath)
         if dirpath is None:
             raise NotFound()
         filepath = osp.join(dirpath, rid)
     return self.static_file(filepath)
Esempio n. 15
0
 def call(self):
     form = self._cw.vreg['forms'].select('sparql', self._cw)
     form.render(w=self.w)
     sparql = self._cw.form.get('sparql')
     vid = self._cw.form.get('resultvid', 'table')
     if sparql:
         try:
             qinfo = Sparql2rqlTranslator(
                 self._cw.vreg.schema).translate(sparql)
         except TypeResolverException as exc:
             self.w(
                 self._cw._('can not resolve entity types:') + u' ' +
                 unicode(exc))
         except UnsupportedQuery:
             self.w(self._cw._('we are not yet ready to handle this query'))
         except xy.UnsupportedVocabulary as exc:
             self.w(self._cw._('unknown vocabulary:') + u' ' + unicode(exc))
         else:
             rql, args = qinfo.finalize()
             if vid == 'sparqlxml':
                 url = self._cw.build_url('view', rql=rql % args, vid=vid)
                 raise Redirect(url)
             rset = self._cw.execute(rql, args)
             self.wview(vid, rset, 'null')
Esempio n. 16
0
 def action_redirect(self, path):
     url = self.action_rewrite(path)
     raise Redirect(url)
Esempio n. 17
0
 def publish(self, rset=None):
     """log in the instance"""
     path = self._cw.form.get('postlogin_path', '')
     # Redirect expects a URL, not a path. Also path may contain a query
     # string, hence should not be given to _cw.build_url()
     raise Redirect(self._cw.base_url() + path)
Esempio n. 18
0
 def call(self, rset=None):
     self._cw.set_header('Cache-Control', 'no-cache')
     raise Redirect('http://example.org')
Esempio n. 19
0
    def call(self, **kwargs):
        """ Create the form fields.

        .. note::

            At upload, all field inputs are checked to match the 'check_value'
            regular expressions defined in the 'upload_structure_json' instance
            parameter.
        """
        # Get some parameters
        path = self._cw.relative_path()
        if "?" in path:
            path, param = path.split("?", 1)
            kwargs.update(parse_qs(param))
        form_name = kwargs["form_name"][0]

        # Get the form fields from configuration file
        config = load_forms(self._cw.vreg.config)

        # Create a structure to store values that must be checked before the
        # insertion in the data base
        check_struct = {}
        required_file_fields = {}

        # Update shortcut to access the uploaded files
        if 0:
            with self._cw.cnx._cnx.repo.internal_cnx() as cnx:
                rset = cnx.execute("Any X Where X is UploadFile")
                storage = cnx.repo.system_source._storages["UploadFile"]["data"]
                for index in range(rset.rowcount):
                    entity = rset.get_entity(index, 0)
                    eid = entity.eid
                    if eid not in self._cw.vreg.uploaded_file_names:
                        fpath = storage.current_fs_path(entity, "data")
                        self._cw.vreg.uploaded_file_names[eid] = fpath

        # If json file missing, generate error page
        if config == -1:
            self.w(u'<div class="panel panel-danger">')
            self.w(u'<div class="panel-heading">')
            self.w(u'<h2 class="panel-title">ERROR</h2>')
            self.w(u'</div>')
            self.w(u'<div class="panel-body">')
            self.w(u"<h3>Configuration file not found</h3>")
            self.w(u"Check that the path 'upload_structure_json' "
                    "declared in all-in-one.conf file is set.<br>")
            self.w(u"Then check that the path declared "
                    "(current path:'{0}') corresponds to a "
                    "json file and restart the instance.".format(
                        self._cw.vreg.config["upload_structure_json"]))
            self.w(u'</div>')
            self.w(u'</div>')
            return -1

        # If json can't be read, generate error page
        if config == -2:
            self.w(u'<div class="panel panel-danger">')
            self.w(u'<div class="panel-heading">')
            self.w(u'<h2 class="panel-title">ERROR</h2>')
            self.w(u'</div>')
            self.w(u'<div class="panel-body">')
            self.w(u"<h3>Configuration unknown</h3>")
            self.w(u"The json file configuring the form can't be "
                    "read: {0}".format(
                        self._cw.vreg.config["upload_structure_json"]))
            self.w(u'</div>')
            self.w(u'</div>')
            return -1

        # Create the form
        form = self._cw.vreg["forms"].select(
            "upload-form", self._cw, action="", form_name=form_name)
        fields_types = {}
        fields_labels = {}
        error_to_display = None
        try:
            # Go through each field description
            for field in config[form_name]["Fields"]:

                # Remove reserved field keys
                # > rql: a RQL that will be used to initialize another field.
                #   The current field must contain a list.
                #   Must be of the form <RQL>:<field_name>.
                #   Format the RQL string with the user login: use '{}' format
                #   synthax in your RQL to inherit from this functionality.
                if "rql" in field:
                    rql, dest_name = field.pop("rql").split(":")
                    rql = rql.format(self._cw.user.login)
                    if dest_name not in field:
                        raise ValueError(
                            "'{0}' not in field attributes.".format(dest_name))
                    if not isinstance(field[dest_name], list):
                        raise ValueError(
                            "'{0}' field attribute is not a list.".format(
                                dest_name))
                    rset = self._cw.execute(rql)
                    for row in rset.rows:
                        field[dest_name].extend(row)
                # > type: the field type that must be declared in the registry
                field_type = field.pop("type")
                fields_types[field["name"]] = field_type
                fields_labels[field["name"]] = field["label"]
                # > style: the css style that will be applied to the field div
                style = None
                if "style" in field:
                    style = field.pop("style")

                # Store the fields that must be checked using a Regex
                if "check_value" in field:
                    check_struct[field["name"]] = field.pop("check_value")

                # Check that the upload directory is created
                # If not display a danger message
                # Store also required file fields
                if field_type in ("FileField", "MultipleFileField"):
                    if not os.path.isdir(
                            self._cw.vreg.config["upload_directory"]):
                        self.w(u"<p class='label label-danger'>{0}: File "
                                "field can't be used because the "
                                "'upload_directory' has not been set in "
                                "all-in-ine.conf file or its path cannot be "
                                "created ({1})</p>".format(
                                    field.pop("label"),
                                    self._cw.vreg.config["upload_directory"]))
                        continue
                    if "required" in field and field["required"]:
                        required_file_fields[field["name"]] = field["label"]

                # If the field is in the registry add the field to the form
                # If requested add some custom styles to the field
                if field_type in DECLARED_FIELDS:
                    form.append_field(DECLARED_FIELDS[field_type](**field))
                    if style is not None:
                        widget = form.field_by_name(
                            field["name"]).get_widget(form)
                        widget.attrs["style"] = unicode(style)
                # Otherwise display a danger message
                else:
                    self.w(
                        u"<p class='label label-danger'>'{0}': Unknown field "
                         "type.</p>".format(field_type))

        # If something goes wrong during the form creation, display a danger
        # message and print the trace in the terminal
        except ValueError as error:
            print traceback.format_exc()
            error_to_display = error.message
        except:
            print traceback.format_exc()
            error_to_display = "The configuration file can't be read."

        # Display the error message
        if error_to_display is not None:
            self.w(u'<div class="panel panel-danger">')
            self.w(u'<div class="panel-heading">')
            self.w(u'<h2 class="panel-title">ERROR</h2>')
            self.w(u'</div>')
            self.w(u'<div class="panel-body">')
            self.w(u'<h3>Configuration file syntax error</h3>')
            self.w(u'{0}<br>'.format(error_to_display))
            self.w(u'Please refer to the documentation and make corrections')
            self.w(u'</div>')
            self.w(u'</div>')
            return -1

        # Form processings
        error_to_display = None
        try:
            # Retrieve the posted form field values
            posted = form.process_posted()

            # Check posted fields
            errors = self.check_posted(posted, required_file_fields,
                                       check_struct)
            if errors != {}:
                raise ValidationError(None, {})

            # Create the CWUpload entity
            upload = self._cw.create_entity(
                "CWUpload",
                form_name=unicode(form_name),
                status=u"Quarantine")

            # Go through the posted form parameters. Deported fields are
            # stored in UploadFile entities, other fields in UploadField
            # entities
            file_eids = []
            field_eids = []
            file_entities = []
            field_entities = []
            for field_name, field_value in posted.items():

                # > files are deported
                if isinstance(field_value, Binary): 

                    # Create an UploadFile entity
                    extension = ".".join(field_value.filename.split(".")[1:])
                    entity = self._cw.create_entity(
                        "UploadFile",
                        name=field_name,
                        data=field_value,
                        data_extension=unicode(extension),
                        data_name=field_value.filename)
                    file_eids.append(entity.eid)
                    file_entities.append(entity)

                    # Add relation with the CWUpload entity
                    self._cw.execute("SET U upload_files F WHERE "
                                     "U eid %(u)s, F eid %(f)s",
                                     {"u": upload.eid, "f" : file_eids[-1]})

                # > other fields are stored in the database
                else:

                    # Create an UploadField entity
                    entity = self._cw.create_entity(
                        "UploadField",
                        name=unicode(field_name),
                        value=unicode(field_value),
                        type=unicode(fields_types[field_name]),
                        label=unicode(fields_labels[field_name]))
                    field_eids.append(entity.eid)
                    field_entities.append(entity)

                    # Add relation with the CWUpload entity
                    self._cw.execute("SET U upload_fields F WHERE "
                                     "U eid %(u)s, F eid %(f)s",
                                     {"u": upload.eid, "f" : field_eids[-1]})

            # Call synchrone check function
            check_func_desc = config[form_name].get("SynchroneCheck")
            if check_func_desc is not None:
                module_name = check_func_desc[:check_func_desc.rfind(".")]
                func_name = check_func_desc[check_func_desc.rfind(".") + 1:]
                module = import_module(module_name)
                check_func = getattr(module, func_name)
                try:
                    error_to_display = check_func(
                        self._cw.cnx, posted, upload, file_entities,
                        field_entities)
                except:
                    exc_type, exc_value, exc_tb = sys.exc_info()
                    raise Exception(traceback.format_exc())
                finally:
                    if error_to_display is not None:
                        raise ValidationError(
                            None, {None: "<br><br>" + error_to_display})

            # Redirection to the created CWUpload entity
            raise Redirect(self._cw.build_url(eid=upload.eid))

        # Handle exceptions
        except RequestError:
            pass
        except ValueError as error:
            error_to_display = error.message
        except ValidationError as error:
            # Check posted fields to concatenate the CW and application errors
            posted = {}
            for field in form.iter_modified_fields():
                posted[field.name] = form._cw.form[field.name]
            errors = self.check_posted(posted, required_file_fields,
                                       check_struct)
            concatenated_errors = {}
            for dict_struct in (errors, error.errors):
                for key, value in dict_struct.items():
                    concatenated_errors.setdefault(key, []).append(value)
            concatenated_errors = dict(
                (key, " - ".join(value))
                for key, value in concatenated_errors.items())
            raise ValidationError(None, concatenated_errors)
        except Redirect:
            raise
        except Unauthorized:
            error_to_display = "You are not allowed to upload data."
        except:
            print traceback.format_exc()
            error_to_display = ("Unexpected error, please contact the service "
                                "administrator.")
            raise ValidationError(
                None, {None: "<br><br>" + error_to_display})

        # Form rendering
        self.w(u"<legend>'{0}' upload form</legend>".format(
            form_name))
        form.render(w=self.w, formvalues=self._cw.form)

        # Display the error message in the page
        if error_to_display is not None:
            self._cw.cnx.rollback()
            self.w(u'<div class="panel panel-danger">')
            self.w(u'<div class="panel-heading">')
            self.w(u'<h2 class="panel-title">ULPLOAD ERROR</h2>')
            self.w(u'</div>')
            self.w(u'<div class="panel-body">')
            self.w(u"{0}".format(error_to_display))
            self.w(u'</div>')
            self.w(u'</div>')
 def publish(self, rset=None):
     raise Redirect(self.success_redirect_url(self.save_data()))