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()
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
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())))
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())
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)
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)
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')))
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')
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)
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())
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)
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))
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)
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)
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')
def action_redirect(self, path): url = self.action_rewrite(path) raise Redirect(url)
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)
def call(self, rset=None): self._cw.set_header('Cache-Control', 'no-cache') raise Redirect('http://example.org')
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()))