def edit_json(context, request): """ Add/Edit form for fields. """ check_csrf_token(request) db_session = request.db_session form = FieldFormFactory(context, request).from_json(request.json_body) if not form.validate(): raise HTTPBadRequest(json={'errors': wtferrors(form)}) is_new = isinstance(context, models.AttributeFactory) if not is_new: attribute = context else: # Add the attribute and temporarily set to large display order attribute = datastore.Attribute(schema=context.__parent__, order=-1) db_session.add(attribute) attribute.apply(form.data) if is_new: # now we can move the attribute move_json(attribute, request) db_session.flush() return view_json(attribute, request)
def edit_json(context, request): """ Adds/Edits a external service record. If the operation was successful, a redirect to the new record details will be returns. Otherwise a json record of validation errors will be returned. """ check_csrf_token(request) dbsession = request.dbsession form = ExternalServiceForm(context, request).from_json(request.json_body) if not form.validate(): return HTTPBadRequest(json={'errors': wtferrors(form)}) if isinstance(context, models.ExternalServiceFactory): study = context.__parent__ service = models.ExternalService(study=study) else: study = context.study service = context service.name = slugify(form.title.data) service.title = form.title.data service.description = form.description.data service.url_template = form.url_template.data dbsession.flush() success_url = request.route_path('studies.external_service', study=study.name, service=service.name) return HTTPSeeOther(location=success_url)
def upload(context, request): """ Allows the user to upload a JSON file form. """ check_csrf_token(request) db_session = request.db_session files = request.POST.getall('files') if len(files) < 1: raise HTTPBadRequest(json={'user_message': _(u'Nothing uploaded')}) names = [] for file_info in files: try: data = json.load(file_info.file) except ValueError: raise HTTPBadRequest( json={'user_message': _(u'Invalid file format uploaded')}) else: schema = datastore.Schema.from_json(data) schema.publish_date = schema.retract_date = None db_session.add(schema) db_session.flush() names.append(schema.name) return get_list_data(request, names=names)
def login(context, request): login_url = request.mgmt_path(request.context, 'login') referrer = request.url if login_url in referrer: # pragma: no cover # never use the login form itself as came_from referrer = request.mgmt_path(request.root) came_from = request.session.setdefault('came_from', referrer) login = '' password = '' if 'form.submitted' in request.params: try: check_csrf_token(request) except: request.session.flash('Failed login (CSRF)', 'error') else: login = request.params['login'] password = request.params['password'] principals = find_service(context, 'principals') users = principals['users'] user = users.get(login) if user is not None and user.check_password(password): headers = remember(request, oid_of(user)) return HTTPFound(location=came_from, headers=headers) request.session.flash('Failed login', 'error') return dict( url=request.mgmt_path(request.root, 'login'), came_from=came_from, login=login, password=password, )
def delete_json(context, request): """ Edits form version metadata (not the fields) """ check_csrf_token(request) db_session = request.db_session db_session.delete(context) if context.publish_date: msg = _(u'Successfully deleted ${name} version ${version}', mapping={ 'name': context.name, 'version': context.publish_date }) else: msg = _(u'Successfully deleted draft of ${name}', mapping={'name': context.name}) request.session.flash(msg) return { # Hint the next resource to look for data '__next__': request.current_route_path(_route_name='forms.index') }
def delete_mappings(context, request): check_csrf_token(request) db_session = request.db_session mappings = request.json['mapped_delete'] records = [] # only delete if all records can be deleted for mapping in mappings: if mapping['deleteRow'] is True: try: mapped = db_session.query(models.Mapping).filter( models.Mapping.id == mapping['mappedId']).one() except NoResultFound: request.response.status = 400 return json.dumps( {'error': 'No record found for id: '.format( mapping['mappedId'])}) except MultipleResultsFound: request.response.status = 400 return json.dumps( {'error': 'Multiple records found for id: '.format( mapping['mappedId'])}) else: records.append(mapped) for record in records: db_session.delete(record) return {}
def edit_json(context, request): check_csrf_token(request) db_session = request.db_session form = EnrollmentSchema(context, request).from_json(request.json_body) if not form.validate(): raise HTTPBadRequest(json={'errors': wtferrors(form)}) if isinstance(context, models.EnrollmentFactory): enrollment = models.Enrollment(patient=context.__parent__, study=form.study.data) else: enrollment = context enrollment.patient.modify_date = datetime.now() enrollment.consent_date = form.consent_date.data enrollment.latest_consent_date = form.latest_consent_date.data enrollment.reference_number = form.reference_number.data if not form.study.data.termination_schema: enrollment.termination_date = form.termination_date.data db_session.flush() return view_json(enrollment, request)
def delete_json(context, request): check_csrf_token(request) db_session = request.db_session for entity in context.entities: db_session.delete(entity) db_session.flush() db_session.delete(context) db_session.flush() viewed = request.session.setdefault('viewed', OrderedDict()) try: del viewed[context.pid] except KeyError: log.warn('This patient was never viewed in the browser') else: request.session.changed() msg = request.localizer.translate( _('Patient ${pid} was successfully removed'), mapping={'pid': context.pid}) request.session.flash(msg, 'success') return { '__next__': request.current_route_path(_route_name='studies.index') }
def delete(context, request): check_csrf_token(request) db_session = request.db_session db_session.remove(context) next_url = request.current_route_path(_route_name='imports.project_list') result = HTTPSeeOther(location=next_url) return result
def patch(context, request): check_csrf_token(request) db_session = request.db_session is_new = isinstance(context, models.ProjectFactory) project = context if not is_new else None schema = ProjectSchema().bind(project=project, request=request) try: data = schema.deserialize(request.POST) except colander.Invalid as e: return HTTPBadRequest(json=e.asdict()) if is_new: project = models.Project( # We don't care about these for mappings short_title=data['name'], consent_date=date.today()) db_session.add(project) project.name = data['name'], project.title = data['title'], next_url = request.current_route_path(_route_name='imports.project_detail', project=project.name) result = HTTPSeeOther(location=next_url) return result
def mappings_direct_map(context, request): check_csrf_token(request) db_session = request.db_session target_study = ( db_session.query(studies.Study) .join(studies.Study.schemata) .filter(datastore.Schema.name == request.json['source_schema']) .filter(datastore.Schema.publish_date == request.json['source_schema_publish_date']).one()) data = request.json if request.json['choices_mapping']: adj_choices_mapping = [] for mapping in request.json['choices_mapping']: for name in mapping['mapped'].split(','): adj_choices_mapping.append({'source': name, 'target': mapping['name']}) data['choices_mapping'] = adj_choices_mapping # add default review status to mapping status = db_session.query(models.Status).filter_by(name=u'review').one() mapped_obj = models.Mapping( study=target_study, status=status, type=u'direct', logic=data ) db_session.add(mapped_obj) db_session.flush() return {'id': mapped_obj.id}
def edit_json(context, request): """ Add/Edit form for fields. """ check_csrf_token(request) dbsession = request.dbsession form = FieldFormFactory(context, request).from_json(request.json_body) if not form.validate(): raise HTTPBadRequest(json={'errors': wtferrors(form)}) is_new = isinstance(context, models.AttributeFactory) if not is_new: attribute = context else: # Add the attribute and temporarily set to large display order attribute = models.Attribute(schema=context.__parent__, order=-1) dbsession.add(attribute) attribute.apply(form.data) if is_new: # now we can move the attribute move_json(attribute, request) dbsession.flush() return view_json(attribute, request)
def detail(request: Request): # Convert base64 encoded UUID string from request path to Python UUID object question_uuid = slug_to_uuid(request.matchdict["question_uuid"]) question = request.dbsession.query(Question).filter_by(uuid=question_uuid).first() if not question: raise HTTPNotFound() if request.method == "POST": # Check that CSRF token was good check_csrf_token(request) question = request.dbsession.query(Question).filter_by(uuid=question_uuid).first() if not question: raise HTTPNotFound() if "choice" in request.POST: # Extracts the form choice and turn it to UUID object chosen_uuid = slug_to_uuid(request.POST["choice"]) selected_choice = question.choices.filter_by(uuid=chosen_uuid).first() selected_choice.votes += 1 messages.add(request, msg="Thank you for your vote", kind="success") return HTTPFound(request.route_url("results", question_uuid=uuid_to_slug(question.uuid))) else: error_message = "You did not select any choice." return locals()
def login(context, request): login_url = request.sdiapi.mgmt_path(request.context, 'login') referrer = request.url if login_url in referrer: # pragma: no cover # never use the login form itself as came_from referrer = request.sdiapi.mgmt_path(request.root) came_from = request.session.setdefault('sdi.came_from', referrer) login = '' password = '' if 'form.submitted' in request.params: try: check_csrf_token(request) except: request.session.flash('Failed login (CSRF)', 'error') else: login = request.params['login'] password = request.params['password'] principals = find_service(context, 'principals') users = principals['users'] user = users.get(login) if user is not None and user.check_password(password): request.session.pop('sdi.came_from', None) headers = remember(request, get_oid(user)) return HTTPFound(location = came_from, headers = headers) request.session.flash('Failed login', 'error') return dict( url = request.sdiapi.mgmt_path(request.root, 'login'), came_from = came_from, login = login, password = password, )
def add(self): check_csrf_token(self.request) objectmap = find_objectmap(self.context) verb = self.request.POST['verb'] principal_id_str = self.request.POST['principal'] if principal_id_str in (Everyone, Authenticated): principal_id = principal_id_str else: try: principal_id = int(principal_id_str) except ValueError: principal_id = None if principal_id is None: self.request.session.flash('No principal selected', 'error') else: if principal_id not in (Everyone, Authenticated): if objectmap.object_for(principal_id) is None: self.request.session.flash( 'Unknown user or group when adding ACE', 'error') principal_id = None if principal_id is not None: permissions = self.request.POST.getall('permissions') if not permissions: permissions = () if '-- ALL --' in permissions: permissions = ALL_PERMISSIONS new = self.acl[:] new.append((verb, principal_id, permissions)) self.acl = new self.request.sdiapi.flash_with_undo('New ACE added') return self.finish_acl_edit()
def changePassword(self): """Deal with password changes. To access the form, the correct val_token must be given as one of the parameters to ensure that only users with access to the email account associated with the account will be able to change the password. """ user_id = self.request.matchdict['user_id'] val_token = self.request.params.get('val_token', '') myform = deform.Form(change_schema, buttons=('submit',)) appstruct = dict(req=dict(val_token=val_token, csrf_token=self.request.session.get_csrf_token())) if self.request.method == 'POST': check_csrf_token(self.request) controls = self.request.POST.items() # get the form controls try: appstruct = myform.validate(controls) # call validate except deform.ValidationFailure as e: # catch the exception return {'form':e.render()} # re-render the form with an exception password = appstruct['req']['password'] val_token = appstruct['req']['val_token'] try: self.jobs_lib.changePassword(user_id, password, val_token) self.request.override_renderer = 'generic_message.mako' return dict(heading="Your Password Has Been Changed", messageList=["Click the Login link above to log in."]) except jobslib.JobsPasswordChangeTokenWrongException: return HTTPNotFound() else: return dict(form=myform.render(appstruct))
def delete_schema_json(context, request): check_csrf_token(request) db_session = request.db_session schema_name = request.matchdict.get('schema') (exists, ) = (db_session.query( db_session.query(models.Study).filter( models.Study.schemata.any(name=schema_name)).filter( models.Study.id == context.id).exists()).one()) if not exists: raise HTTPNotFound() # Remove from cycles db_session.execute(models.cycle_schema_table.delete().where( models.cycle_schema_table.c.cycle_id.in_( db_session.query(models.Cycle.id).filter_by( study=context).subquery()) & models.cycle_schema_table.c.schema_id.in_( db_session.query(datastore.Schema.id).filter_by( name=schema_name).subquery()))) # Remove from study db_session.execute(models.study_schema_table.delete().where( (models.study_schema_table.c.study_id == context.id) & (models.study_schema_table.c.schema_id.in_( db_session.query(datastore.Schema.id).filter_by( name=schema_name).subquery())))) mark_changed(db_session) # Expire relations so they load their updated values db_session.expire_all() return HTTPOk()
def merge(request): '''A simple merge view. The merge.mako template does the work.''' s = DBSession() # only do a merge if we have all of the required data if request.params.has_key("csrf_token"): # check the token to prevent request forgery st = request.session.get_csrf_token() check_csrf_token(request) if request.params.has_key("w_pid") and request.params.has_key("l_pid"): w_pid = request.params.get("w_pid") l_pid = request.params.get("l_pid") # do the merge, hope for the best! try: s.execute("select merge_players(:w_pid, :l_pid)", { "w_pid": w_pid, "l_pid": l_pid }) s.commit() request.session.flash( "Successfully merged player %s into %s!" % (l_pid, w_pid), "success") except: s.rollback() request.session.flash( "Could not merge player %s into %s." % (l_pid, w_pid), "failure") return {}
def mappings_direct_map(context, request): check_csrf_token(request) db_session = request.db_session target_study = (db_session.query(studies.Study).join( studies.Study.schemata).filter( datastore.Schema.name == request.json['source_schema']).filter( datastore.Schema.publish_date == request.json['source_schema_publish_date']).one()) data = request.json if request.json['choices_mapping']: adj_choices_mapping = [] for mapping in request.json['choices_mapping']: for name in mapping['mapped'].split(','): adj_choices_mapping.append({ 'source': name, 'target': mapping['name'] }) data['choices_mapping'] = adj_choices_mapping # add default review status to mapping status = db_session.query(models.Status).filter_by(name=u'review').one() mapped_obj = models.Mapping(study=target_study, status=status, type=u'direct', logic=data) db_session.add(mapped_obj) db_session.flush() return {'id': mapped_obj.id}
def patch(context, request): check_csrf_token(request) db_session = request.db_session is_new = isinstance(context, models.ProjectFactory) project = context if not is_new else None schema = ProjectSchema().bind(project=project, request=request) try: data = schema.deserialize(request.POST) except colander.Invalid as e: return HTTPBadRequest(json=e.asdict()) if is_new: project = models.Project( # We don't care about these for mappings short_title=data['name'], consent_date=date.today() ) db_session.add(project) project.name = data['name'], project.title = data['title'], next_url = request.current_route_path( _route_name='imports.project_detail', project=project.name ) result = HTTPSeeOther(location=next_url) return result
def edit_json(context, request): check_csrf_token(request) db_session = request.db_session form = StudySchema(context, request).from_json(request.json_body) if not form.validate(): raise HTTPBadRequest(json={'errors': wtferrors(form)}) if isinstance(context, models.StudyFactory): study = models.Study() db_session.add(study) else: study = context study.name = slugify(form.title.data) study.title = form.title.data study.code = form.code.data study.short_title = form.short_title.data study.consent_date = form.consent_date.data study.termination_schema = form.termination_form.data study.is_randomized = form.is_randomized.data study.is_blinded = \ None if not study.is_randomized else form.is_blinded.data study.randomization_schema = \ None if not study.is_randomized else form.randomization_form.data db_session.flush() return view_json(study, request)
def bulk_delete_json(context, request): """ Deletes forms in bulk """ check_csrf_token(request) db_session = request.db_session class DeleteForm(Form): forms = wtforms.FieldList( ModelField(db_session=db_session, class_=datastore.Entity), validators=[wtforms.validators.DataRequired()]) form = DeleteForm.from_json(request.json_body) if not form.validate(): raise HTTPBadRequest(json={'errors': wtferrors(form)}) entity_ids = [entity.id for entity in form.forms.data] external = context.__parent__.__tablename__ key = context.__parent__.id (db_session.query(datastore.Entity).filter( datastore.Entity.id.in_( db_session.query(datastore.Context.entity_id).filter( datastore.Context.entity_id.in_(entity_ids)).filter( datastore.Context.external == external).filter( datastore.Context.key == key))).delete('fetch')) db_session.flush() return HTTPOk()
def removeListing(self): """Deal with the listing removal page. The user is asked to give the reason they are removing the listing, then it is removed. """ listing_id = self.request.matchdict.get('listing_id', None) if listing_id: listing = self.jobs_lib.getListingById(listing_id) if listing.user_id != self.request.authenticated_userid: return HTTPForbidden() myform = Form(removeSchema, buttons=('Remove Listing',)) if self.request.method == 'POST': check_csrf_token(self.request) controls = self.request.POST.items() # get the form controls try: appstruct = myform.validate(controls) # call validate except deform.ValidationFailure as e: # catch the exception return {'form':e.render()} # re-render the form with an exception user = self.jobs_lib.getUserById(self.request.authenticated_userid) if not listing.removal_reason: self.jobs_lib.removeListing(user, listing, appstruct['removal_reason']) self.request.override_renderer = 'generic_message.mako' return dict(heading="Listing Removed", messageList=["Your listing will no longer appear on the site.", "Thank you for using %s." % self.request.registry.settings['jobs.sitename']]) else: appstruct = dict(csrf_token=self.request.session.get_csrf_token()) return dict(form=myform.render(appstruct))
def upload(context, request): """ Allows the user to upload a JSON file form. """ check_csrf_token(request) dbsession = request.dbsession files = request.POST.getall('files') if len(files) < 1: raise HTTPBadRequest(json={'user_message': _(u'Nothing uploaded')}) names = [] for file_info in files: try: data = json.load(file_info.file) except ValueError: raise HTTPBadRequest( json={'user_message': _(u'Invalid file format uploaded')}) else: schema = models.Schema.from_json(data) schema.publish_date = schema.retract_date = None dbsession.add(schema) dbsession.flush() names.append(schema.name) return get_list_data(request, names=names)
def add_blog(request): log.info('start add blog') if 'form.submitted' in request.params: check_csrf_token(request) user_id = request.session['user_id'] default_class_id = DBSession().query(BlogClass).filter_by(id = request.session['user_id'], name = 'all').one() blog = Blog(title = request.params['title'], content = request.params['content'], created_time = datetime.today(), ) # created_time = cgi.escape(request.params['content'])) DBSession.add(blog) # insert blog blog_class realtionships blogclass_names = request.params['class_names'].split(';') for blogclass_name in blogclass_names: blogclass = DBSession().query(BlogClass).filter_by( name = blog_class.name).one() blog = DBSession().query(Blog).filter_by( title = blog.title).one() blog_blogclass = Blog_BlogClass(blog_id= blog.id, blogclass_id = blogclass.id) DBSession.add(blog_blogclass) log.info('add_blog submitted') return HTTPFound(request.route_url('view_blog' )) log.info('add_blog view') return dict()
def persona_login(context, request): check_csrf_token(request) email = verify_persona_assertion(request) root = root_factory(request) adapter = request.registry.queryMultiAdapter( (root, request), IUserLocator) if adapter is None: adapter = DefaultUserLocator(root, request) user = adapter.get_user_by_email(email) if user is None: registry = request.registry username = '******' % email principals = find_service(root, 'principals') user = principals.add_user(username, registry=registry) user.email = email performer = registry.content.create('Performer') root['performers'][username] = performer performer.user = user set_acl(performer, [(Allow, user.__oid__, ['yss.edit-profile'])]) location = request.resource_url(performer, 'edit.html') performer.title = email performer.email = email performer.photo_url = persona_gravatar_photo(request, email) performer.age = colander.null performer.sex = user.favorite_genre = None location = request.resource_url(performer, 'edit.html') else: location = request.resource_url(root['performers'][user.__name__]) headers = remember(request, get_oid(user)) request.response.headers.extend(headers) return {'redirect': location, 'success': True}
def edit_json(context, request): check_csrf_token(request) db_session = request.db_session form = EnrollmentSchema(context, request).from_json(request.json_body) if not form.validate(): raise HTTPBadRequest(json={'errors': wtferrors(form)}) if isinstance(context, models.EnrollmentFactory): enrollment = models.Enrollment( patient=context.__parent__, study=form.study.data) else: enrollment = context enrollment.patient.modify_date = datetime.now() enrollment.consent_date = form.consent_date.data enrollment.latest_consent_date = form.latest_consent_date.data enrollment.reference_number = form.reference_number.data if not form.study.data.termination_schema: enrollment.termination_date = form.termination_date.data db_session.flush() return view_json(enrollment, request)
def machine_reconfigure(request): """ Handler for POST requests to ``/{org}/machine/{id}/reconfigure``. The user must be authenticated for the organisation in the URL to reach here. Attempt to reconfigure the specified machine with the given amount of CPU and RAM. """ # Request must pass a CSRF test check_csrf_token(request) try: cpus = int(request.params['cpus']) ram = int(request.params['ram']) if cpus < 1 or ram < 1: raise ValueError('CPU and RAM must be at least 1') except (ValueError, KeyError): # If the user has used the UI without modification, this should never happen request.session.flash('Error with inputs', 'error') return HTTPSeeOther(location = request.route_url('machines')) # Reconfigure the machine machine_id = request.matchdict['id'] request.active_cloud_session.reconfigure_machine(machine_id, cpus, ram) request.session.flash('Machine reconfigured successfully', 'success') return HTTPSeeOther(location = request.route_url('machines'))
def machine_reconfigure(request): """ Handler for POST requests to ``/{org}/machine/{id}/reconfigure``. The user must be authenticated for the organisation in the URL to reach here. Attempt to reconfigure the specified machine with the given amount of CPU and RAM. """ # Request must pass a CSRF test check_csrf_token(request) try: cpus = int(request.params['cpus']) ram = int(request.params['ram']) if cpus < 1 or ram < 1: raise ValueError('CPU and RAM must be at least 1') except (ValueError, KeyError): # If the user has used the UI without modification, this should never happen request.session.flash('Error with inputs', 'error') return HTTPSeeOther(location=request.route_url('machines')) # Reconfigure the machine machine_id = request.matchdict['id'] request.active_cloud_session.reconfigure_machine(machine_id, cpus, ram) request.session.flash('Machine reconfigured successfully', 'success') return HTTPSeeOther(location=request.route_url('machines'))
def delete_json(context, request): check_csrf_token(request) dbsession = request.dbsession for entity in context.entities: dbsession.delete(entity) dbsession.flush() dbsession.delete(context) dbsession.flush() viewed = request.session.setdefault('viewed', OrderedDict()) try: del viewed[context.pid] except KeyError: log.warn('This patient was never viewed in the browser') else: request.session.changed() msg = request.localizer.translate( _('Patient ${pid} was successfully removed'), mapping={'pid': context.pid}) request.session.flash(msg, 'success') return { '__next__': request.current_route_path(_route_name='studies.index') }
def add(self): check_csrf_token(self.request) objectmap = find_objectmap(self.context) verb = self.request.POST['verb'] principal_id_str = self.request.POST['principal'] if principal_id_str in (Everyone, Authenticated): principal_id = principal_id_str else: try: principal_id = int(principal_id_str) except ValueError: principal_id = None if principal_id is None: self.request.sdiapi.flash('No principal selected', 'danger') else: if principal_id not in (Everyone, Authenticated): if objectmap.object_for(principal_id) is None: self.request.sdiapi.flash( 'Unknown user or group when adding ACE', 'danger') principal_id = None if principal_id is not None: permissions = self.request.POST.getall('permissions') if not permissions: permissions = () if '-- ALL --' in permissions: permissions = ALL_PERMISSIONS new = self.acl[:] new.append((verb, principal_id, permissions)) self.acl = new self.request.sdiapi.flash_with_undo('New ACE added', 'success') return self.finish_acl_edit()
def merge(request): '''A simple merge view. The merge.mako template does the work.''' s = DBSession() # only do a merge if we have all of the required data if request.params.has_key("csrf_token"): # check the token to prevent request forgery st = request.session.get_csrf_token() check_csrf_token(request) if request.params.has_key("w_pid") and request.params.has_key("l_pid"): w_pid = request.params.get("w_pid") l_pid = request.params.get("l_pid") # do the merge, hope for the best! try: s.execute("select merge_players(:w_pid, :l_pid)", {"w_pid": w_pid, "l_pid": l_pid}) s.commit() request.session.flash( "Successfully merged player %s into %s!" % (l_pid, w_pid), "success") except: s.rollback() request.session.flash( "Could not merge player %s into %s." % (l_pid, w_pid), "failure") return {}
def edit_schedule_json(context, request): """ Enables/Disables a form for a cycle Request body json parameters: schema -- name of the schema (will used study-enabled versions) cycle -- cycle id enabled -- true/false """ check_csrf_token(request) db_session = request.db_session def check_cycle_association(form, field): if field.data.study != context: raise wtforms.ValidationError( request.localizer.translate(_(u'Not a valid choice'))) def check_form_association(form, field): query = (db_session.query(datastore.Schema).join( models.study_schema_table).filter( datastore.Schema.name == field.data).filter( models.study_schema_table.c.study_id == context.id)) (exists, ) = db_session.query(query.exists()).one() if not exists: raise wtforms.ValidationError( request.localizer.translate(_(u'Not a valid choice'))) class ScheduleForm(Form): schema = wtforms.StringField(validators=[ wtforms.validators.InputRequired(), check_form_association ]) cycle = ModelField(db_session=db_session, class_=models.Cycle, validators=[ wtforms.validators.InputRequired(), check_cycle_association ]) enabled = wtforms.BooleanField() form = ScheduleForm.from_json(request.json_body) if not form.validate(): raise HTTPBadRequest(json={'errors': wtferrors(form)}) schema_name = form.schema.data cycle = form.cycle.data enabled = form.enabled.data study_items = set(i for i in context.schemata if i.name == schema_name) cycle_items = set(i for i in cycle.schemata if i.name == schema_name) if enabled: # Match cycle schemata to the study's schemata for the given name cycle.schemata.difference_update(cycle_items - study_items) cycle.schemata.update(study_items) else: cycle.schemata.difference_update(study_items | cycle_items) return HTTPOk()
def wrapper(cls): request = cls.request errors = cls.validation_errors = dict() cls.validation_results = dict() if request.method.upper() in self.methods: if self.allow_json and \ request.content_type.startswith('application/json'): # Parse JSON body instead of HTTP POST vars try: params = request.json except: raise HTTPBadRequest else: # Don't verify CSRF for JSON requests, as Auth headers # should always be sent. self.verify_csrf = False elif len(self.methods) > 1: params = request.params.mixed() else: params = getattr(request, self.methods[0]) # Validate CSRF if self.verify_csrf and request.method.upper() == 'POST': check_csrf_token(request) del params['csrf_token'] # Validate Schema if self.schema: try: cls.validation_results = self.schema.to_python( params, self.state ) except Invalid as err: if NestedVariables in getattr(self.schema, 'pre_validators', []): try: errors = err.unpack_errors(True) except: errors = err.unpack_errors(False) else: errors = err.unpack_errors(False) # Validate Validators if self.validators: for field, validator in self.validators.items(): try: cls.validation_results[field] = \ validator.to_python(params.get(field), self.state) except Invalid as err: errors[field] = err if errors: cls.validation_errors = errors if isinstance(errors, dict) \ else dict(_global=errors) return fn(cls)
def catalogue_new(request): """ Handler for ``/{org}/catalogue/new/{id}`` The user must be authenticated for the organisation in the URL to reach here. ``{id}`` is the uuid of the machine to use as a template. GET request Show a form to gather information required to create a new catalogue item. POST request Attempt to create a new catalogue item using the provided information. On success, redirect the user to ``/{org}/catalogue`` with a success message. On a duplicate name error, show the form with an error message. """ # Get the cloud session for the current org cloud_session = request.active_cloud_session # Check if the session has permission to create templates if not cloud_session.has_permission('CAN_CREATE_TEMPLATES'): raise HTTPForbidden() # Get the machine details from the id machine = cloud_session.get_machine(request.matchdict['id']) # On a POST request, we must try to create the catalogue item if request.method == 'POST': # All POST requests need a csrf token check_csrf_token(request) item_info = { 'name': request.params.get('name', ''), 'description': request.params.get('description', ''), } try: # Create the catalogue item cloud_session.image_from_machine(machine.id, item_info['name'], item_info['description']) request.session.flash('Catalogue item created successfully', 'success') except cloudservices.DuplicateNameError: request.session.flash('There are errors with one or more fields', 'error') return { 'machine': machine, 'item': item_info, 'errors': { 'name': ['Catalogue item name is already in use'] } } return HTTPSeeOther(location=request.route_url('catalogue')) # Only a get request should get this far return { 'machine': machine, 'item': { 'name': '', 'description': '', }, 'errors': {} }
def delete_json(context, request): check_csrf_token(request) db_session = request.db_session db_session.delete(context) db_session.flush() msg = _(u'Successfully deleted: ${site}', mapping={'site': context.title}) request.session.flash(msg) return HTTPOk(body=msg)
def delete_json(context, request): check_csrf_token(request) dbsession = request.dbsession dbsession.delete(context) dbsession.flush() msg = _(u'Successfully deleted: ${site}', mapping={'site': context.title}) request.session.flash(msg) return HTTPOk(body=msg)
def delete_json(context, request): """ Deletes the field from the form """ check_csrf_token(request) dbsession = request.dbsession dbsession.delete(context) return HTTPOk()
def remove(self): check_csrf_token(self.request) index = int(self.request.POST['index']) new = self.acl[:] del new[index] self.acl = new self.request.sdiapi.flash_with_undo('ACE removed') return self.finish_acl_edit()
def logout(self): # Don't allow <img src="http://server/logout"> assert self.request.method == "POST" check_csrf_token(self.request) self.request.session.invalidate() messages.add(self.request, msg="You are now logged out.", kind="success", msg_id="msg-logged-out") headers = forget(self.request) return HTTPFound(location=self.logout_redirect_view, headers=headers)
def delete_json(context, request): """ Deletes the field from the form """ check_csrf_token(request) db_session = request.db_session db_session.delete(context) return HTTPOk()
def remove(self): check_csrf_token(self.request) index = int(self.request.POST['index']) new = self.acl[:] del new[index] self.acl = new self.request.sdiapi.flash_with_undo('ACE removed', 'success') return self.finish_acl_edit()
def move_json(context, request): """ Moves the field to the target section and display order within the form """ check_csrf_token(request) db_session = request.db_session schema = context.schema def not_self(form, field): if field.data == context.name: raise wtforms.ValidationError(_(u'Cannot move value into itself')) def not_section(form, field): if (context.type == 'section' and schema.attributes[field.data].type == 'section'): raise wtforms.ValidationError( _(u'Nested sections are not supported')) class MoveForm(Form): target = wtforms.StringField( validators=[ wtforms.validators.Optional(), wtforms.validators.AnyOf( schema.attributes, message=_(u'Does not exist')), not_self, not_section]) index = wtforms.IntegerField( validators=[wtforms.validators.NumberRange(min=0)]) form = MoveForm.from_json(request.json_body) if not form.validate(): raise HTTPBadRequest(json={'errors': wtferrors(form)}) if form.target.data: section = target = schema.attributes[form.target.data] else: target = schema section = None attributes = [a for a in target.itertraverse() if a != context] context.parent_attribute = section attributes.insert(form.index.data, context) # Apply new display orders before re-sorting the entire list for i, a in enumerate(attributes): a.order = i # We need to resort the fields to avoid ordering collisions for i, a in enumerate(schema.iterlist()): a.order = i db_session.flush() return HTTPOk()
def edit_json(context, request): check_csrf_token(request) dbsession = request.dbsession is_new = isinstance(context, models.PatientFactory) form = PatientSchema(context, request).from_json(request.json_body) if not form.validate(): raise HTTPBadRequest(json={'errors': wtferrors(form)}) if is_new: # if any errors occurr after this, this PID is essentially wasted patient = models.Patient( pid=six.text_type(generate(dbsession, form.site.data.name))) dbsession.add(patient) else: patient = context patient.site = form.site.data if form.references.data: inputs = dict( ((r['reference_type'].id, r['reference_number']), r) for r in form.references.data) for r in patient.references: try: # Remove already-existing values from the inputs del inputs[(r.reference_type.id, r.reference_number)] except KeyError: # References not in the inputs indicate they have been removed dbsession.delete(r) for r in six.itervalues(inputs): dbsession.add(models.PatientReference( patient=patient, reference_type=r['reference_type'], reference_number=r['reference_number'])) # Add the patient forms if is_new: schemata_query = ( dbsession.query(models.Schema) .join(models.patient_schema_table)) pending_entry = ( dbsession.query(models.State) .filter_by(name=u'pending-entry') .one()) for schema in schemata_query: patient.entities.add(models.Entity( schema=schema, state=pending_entry )) dbsession.flush() dbsession.refresh(patient) return view_json(patient, request)
def move_json(context, request): """ Moves the field to the target section and display order within the form """ check_csrf_token(request) dbsession = request.dbsession schema = context.schema def not_self(form, field): if field.data == context.name: raise wtforms.ValidationError(_(u'Cannot move value into itself')) def not_section(form, field): if (context.type == 'section' and schema.attributes[field.data].type == 'section'): raise wtforms.ValidationError( _(u'Nested sections are not supported')) class MoveForm(Form): target = wtforms.StringField( validators=[ wtforms.validators.Optional(), wtforms.validators.AnyOf( schema.attributes, message=_(u'Does not exist')), not_self, not_section]) index = wtforms.IntegerField( validators=[wtforms.validators.NumberRange(min=0)]) form = MoveForm.from_json(request.json_body) if not form.validate(): raise HTTPBadRequest(json={'errors': wtferrors(form)}) if form.target.data: section = target = schema.attributes[form.target.data] else: target = schema section = None attributes = [a for a in target.itertraverse() if a != context] context.parent_attribute = section attributes.insert(form.index.data, context) # Apply new display orders before re-sorting the entire list for i, a in enumerate(attributes): a.order = i # We need to resort the fields to avoid ordering collisions for i, a in enumerate(schema.iterlist()): a.order = i dbsession.flush() return HTTPOk()
def mappings_imputations_map(context, request): check_csrf_token(request) db_session = request.db_session # TODO - find a better way to obtain the site schema_obj = request.json['groups'][0]['conversions'][0]['value']['schema'] study_form_name = schema_obj['name'] study_form_publish_date = schema_obj['publish_date'] study = ( db_session.query(studies.Study) .join(studies.Study.schemata) .filter(datastore.Schema.name == study_form_name) .filter(datastore.Schema.publish_date == study_form_publish_date)).one() mapped_attribute = ( db_session.query(datastore.Attribute) .filter(datastore.Attribute.name == request.json['target']['attribute']['name']) .filter(datastore.Attribute.schema.has( name=request.json['target']['schema']['name'], publish_date=request.json['target']['schema']['publish_date'])) .one()) mapped_choice_data = request.json.get('targetChoice') if mapped_choice_data: mapped_choice = mapped_attribute.choices[mapped_choice_data['name']] else: mapped_choice = None logic = {} logic['groups'] = request.json['groups'] logic['condition'] = request.json['condition'] logic['target_schema'] = request.json['target']['schema']['name'] logic['target_variable'] = request.json['target']['attribute']['name'] logic['forms'] = [] for group in request.json['groups']: for conversion in group['conversions']: if isinstance(conversion['value'], dict): form_name = conversion['value']['schema']['name'] variable = conversion['value']['attribute']['name'] logic['forms'].append([form_name, variable]) # add default review status to mapping status = db_session.query(models.Status).filter_by(name='review').one() mapped_obj = models.Mapping( study=study, type='imputation', status=status, description=request.json['description'], logic=logic ) db_session.add(mapped_obj) db_session.flush() return {'__next__': request.route_path('imports.index')}
def move_up(self): check_csrf_token(self.request) index = int(self.request.POST['index']) if index > 0: new = self.acl[:] new[index-1], new[index] = new[index], new[index-1] self.acl = new self.request.sdiapi.flash_with_undo('ACE moved up', 'success') return self.finish_acl_edit()
def move_down(self): check_csrf_token(self.request) index = int(self.request.POST['index']) if index < len(self.acl) - 1: new = self.acl[:] new[index + 1], new[index] = new[index], new[index + 1] self.acl = new self.request.sdiapi.flash_with_undo('ACE moved down') return self.finish_acl_edit()
def move_down(self): check_csrf_token(self.request) index = int(self.request.POST['index']) if index < len(self.acl) - 1: new = self.acl[:] new[index+1], new[index] = new[index], new[index+1] self.acl = new self.request.sdiapi.flash_with_undo('ACE moved down', 'success') return self.finish_acl_edit()
def reindex(self): context = self.context request = self.request check_csrf_token(request) oid = get_oid(context) for catalog in find_catalogs(context): catalog.reindex_doc(oid, context) request.sdiapi.flash_with_undo('Object reindexed', 'success') return HTTPFound(request.sdiapi.mgmt_url(context, '@@indexing'))
def move_up(self): check_csrf_token(self.request) index = int(self.request.POST['index']) if index > 0: new = self.acl[:] new[index-1], new[index] = new[index], new[index-1] self.acl = new self.request.sdiapi.flash_with_undo('ACE moved up') return self.finish_acl_edit()
def catalogue_new(request): """ Handler for ``/{org}/catalogue/new/{id}`` The user must be authenticated for the organisation in the URL to reach here. ``{id}`` is the uuid of the machine to use as a template. GET request Show a form to gather information required to create a new catalogue item. POST request Attempt to create a new catalogue item using the provided information. On success, redirect the user to ``/{org}/catalogue`` with a success message. On a duplicate name error, show the form with an error message. """ # Get the cloud session for the current org cloud_session = request.active_cloud_session # Check if the session has permission to create templates if not cloud_session.has_permission('CAN_CREATE_TEMPLATES'): raise HTTPForbidden() # Get the machine details from the id machine = cloud_session.get_machine(request.matchdict['id']) # On a POST request, we must try to create the catalogue item if request.method == 'POST': # All POST requests need a csrf token check_csrf_token(request) item_info = { 'name' : request.params.get('name', ''), 'description' : request.params.get('description', ''), } try: # Create the catalogue item cloud_session.image_from_machine( machine.id, item_info['name'], item_info['description'] ) request.session.flash('Catalogue item created successfully', 'success') except cloudservices.DuplicateNameError: request.session.flash('There are errors with one or more fields', 'error') return { 'machine' : machine, 'item' : item_info, 'errors' : { 'name' : ['Catalogue item name is already in use'] } } return HTTPSeeOther(location = request.route_url('catalogue')) # Only a get request should get this far return { 'machine' : machine, 'item' : { 'name' : '', 'description' : '', }, 'errors' : {} }
def get_status_and_notes(context, request): check_csrf_token(request) db_session = request.db_session mapping_id = int(request.params['id']) mapping = db_session.query(models.Mapping).filter_by(id=mapping_id).one() status = mapping.status.name notes = mapping.notes return {'status': status, 'notes': notes}
def csrf_view(context, request): # Assume that anything not defined as 'safe' by RFC2616 needs # protection if (request.method not in SAFE_REQUEST_METHODS and ( # skip exception views unless value is explicitly defined getattr(request, 'exception', None) is None or explicit_val is not None)): check_csrf_origin(request, raises=True) check_csrf_token(request, resolved_val, raises=True) return view(context, request)
def publish_json(context, request): check_csrf_token(request) db_session = request.db_session def check_unique_publish_date(form, field): (exists,) = ( db_session.query( db_session.query(datastore.Schema) .filter_by(name=context.name, publish_date=field.data) .filter(datastore.Schema.id != context.id) .exists()) .one()) if exists: raise wtforms.ValidationError(_( 'Version ${publish_date} is already in use', mapping={'publish_date': field.data})) def check_valid_timeline(form, field): publish_date = form.publish_date.data retract_date = form.retract_date.data if not publish_date: raise wtforms.ValidationError(_( u'Cannot retract an un-published form')) if retract_date < publish_date: raise wtforms.ValidationError(_('Must be after publish date')) # TODO: should move this out, but need to ensure context is removed # from helper validators class PublishForm(Form): publish_date = wtforms.ext.dateutil.fields.DateField( validators=[ wtforms.validators.Optional(), DateRange(min=date(1900, 1, 1)), check_unique_publish_date ], widget=wtforms.widgets.html5.DateInput()) retract_date = wtforms.ext.dateutil.fields.DateField( validators=[ wtforms.validators.Optional(), DateRange(min=date(1900, 1, 1)), check_valid_timeline ], widget=wtforms.widgets.html5.DateInput()) form = PublishForm.from_json(request.json_body) if not form.validate(): return HTTPBadRequest(json={'errors': form.errors}) context.publish_date = form.publish_date.data context.retract_date = form.retract_date.data db_session.flush() return view_json(context, request)
def delete_json(context, request): """ Handles delete delete AJAX request """ dbsession = request.dbsession check_csrf_token(request) export = context dbsession.delete(export) dbsession.flush() tasks.app.control.revoke(export.name) return HTTPOk()