def scan_comment(scan_id): """ View for adding scan comments """ form = ScanCommentForm() form.user_id = current_user.id form.scan_id = scan_id scan = Scan.query.get(scan_id) session = scan.session if not current_user.has_study_access(session.study): flash('Not authorised') return redirect(url_for('index')) if form.validate_on_submit(): try: scancomment = ScanComment() scancomment.scan_id = scan_id scancomment.user_id = current_user.id scancomment.analysis_id = form.analyses.data scancomment.excluded = form.excluded.data scancomment.comment = form.comment.data db.session.add(scancomment) db.session.commit() flash('Scan comment added') except: flash('Failed adding comment') return redirect(url_for('session', session_id=session.id))
def create_issue(session_id, issue_title="", issue_body=""): """ Post a session issue to github, returns to the session view """ session = Session.query.get(session_id) if not current_user.has_study_access(session.study): flash("Not authorised") return redirect(url_for('index')) token = flask_session['active_token'] if issue_title and issue_body: try: gh = Github(token) repo = gh.get_user("TIGRLab").get_repo("Admin") iss = repo.create_issue(issue_title, issue_body) session.gh_issue = iss.number db.session.commit() flash("Issue '{}' created!".format(issue_title)) except: flash( "Issue '{}' was not created successfully.".format(issue_title)) else: flash("Please enter both an issue title and description.") return (redirect(url_for('session', session_id=session.id)))
def todo(study_id=None): """ Runs the datman binary dm-qc-todo.py and returns the results as a json object """ if study_id: study = Study.query.get(study_id) study_name = study.nickname else: study_name = None if not current_user.has_study_access(study_id): flash('Not authorised') return redirect(url_for('index')) # todo_list = utils.get_todo(study_name) try: todo_list = utils.get_todo(study_name) except utils.TimeoutError: # should do something nicer here todo_list = {'error': 'timeout'} except RuntimeError as e: todo_list = {'error': 'runtime:{}'.format(e)} except: todo_list = {'error': 'other'} return jsonify(todo_list)
def get_timepoint(study_id, timepoint_id, current_user): timepoint = Timepoint.query.get(timepoint_id) if timepoint is None: flash("Timepoint {} does not exist".format(timepoint_id)) raise RequestRedirect(url_for("main.index")) if (not current_user.has_study_access(study_id, timepoint.site_id) or not timepoint.belongs_to(study_id)): flash("Not authorised to view {}".format(timepoint_id)) raise RequestRedirect(url_for("main.index")) return timepoint
def scan(scan_id=None): """ Default view for a single scan """ if scan_id is None: flash('Invalid scan') return redirect(url_for('index')) # Check the user has permission to see this study studies = current_user.get_studies() scan = Scan.query.get(scan_id) if not current_user.has_study_access(scan.session.study): flash('Not authorised') return redirect(url_for('index')) # form for updating the study blacklist.csv on the filesystem bl_form = ScanBlacklistForm() # form used for updating the analysis comments scancomment_form = ScanCommentForm() if not bl_form.is_submitted(): # this isn't an update so just populate the blacklist form with current values from the database # these should be the same as in the filesystem bl_form.scan_id = scan_id bl_form.bl_comment.data = scan.bl_comment if bl_form.validate_on_submit(): # going to make an update to the blacklist # update the scan object in the database with info from the form # updating the databse object automatically syncronises blacklist.csv on the filesystem # see models.py scan.bl_comment = bl_form.bl_comment.data try: db.session.add(scan) db.session.commit() flash("Blacklist updated") return redirect(url_for('session', session_id=scan.session_id)) except SQLAlchemyError as err: logger.error('Scan blacklist update failed:{}'.format(str(err))) flash('Update failed, admins have been notified, please try again') return render_template('scan.html', studies=studies, scan=scan, blacklist_form=bl_form, scancomment_form=scancomment_form)
def get_scan(scan_id, study_id, current_user, fail_url=None): if not fail_url: fail_url = url_for('main.index') scan = Scan.query.get(scan_id) if scan is None: logger.error("User {} attempted to retrieve scan with ID {}. " "Retrieval failed.".format(current_user, scan_id)) flash("Scan does not exist.") raise RequestRedirect(fail_url) timepoint = scan.session.timepoint if (not current_user.has_study_access(study_id, timepoint.site_id) or not timepoint.belongs_to(study_id)): flash("Not authorized to view {}".format(scan.name)) raise RequestRedirect(fail_url) return scan
def study(study_id=None, active_tab=None): """ This is the main view for a single study. The page is a tabulated view, I would have done this differently given another chance. """ if not current_user.has_study_access(study_id): flash('Not authorised') return redirect(url_for('index')) # get the list of metrics to be displayed in the graph pages from the study config display_metrics = app.config['DISPLAY_METRICS'] # get the study object from the database study = Study.query.get(study_id) # this is used to update the readme text file form = StudyOverviewForm() if form.validate_on_submit(): # form has been submitted check for changes # simple MD seems to replace \n with \r\n form.readme_txt.data = form.readme_txt.data.replace('\r', '') # also strip blank lines at the start and end as these are # automatically stripped when the form is submitted if not form.readme_txt.data.strip() == study.read_me: study.read_me = form.readme_txt.data study.save() form.readme_txt.data = study.read_me form.study_id.data = study_id return render_template('study.html', metricnames=study.get_valid_metric_names(), study=study, form=form, active_tab=active_tab, display_metrics=display_metrics)
def session_by_name(session_name=None): """ Basically just a helper view, converts a session name to a sesssion_id and returns the session view """ if session_name is None: return redirect('/index') # Strip any file extension or qc_ prefix session_name = session_name.replace('qc_', '') session_name = os.path.splitext(session_name)[0] q = Session.query.filter(Session.name == session_name) if q.count() < 1: flash('Session not found') return redirect(url_for('index')) session = q.first() if not current_user.has_study_access(session.study): flash('Not authorised') return redirect(url_for('index')) return redirect(url_for('session', session_id=session.id))
def scan_blacklist(scan_id): """ View for adding scan comments """ form = ScanBlacklistForm() form.scan_id = scan_id scan = Scan.query.get(scan_id) session = scan.session if not current_user.has_study_access(session.study): flash('Not authorised') return redirect(url_for('index')) if form.validate_on_submit(): try: scan.bl_comment = form.bl_comment.data db.session.commit() flash('Scan blacklisted') except: flash('Failed blacklisting scan') return redirect(url_for('session', session_id=session.id))
def study(study_id=None, active_tab=None): """ This is the main view for a single study. The page is a tabulated view, I would have done this differently given another chance. """ if study_id is None: return redirect('/index') #study_id = current_user.get_studies()[0].id # get the study object from the database study = Study.query.get(study_id) if not current_user.has_study_access(study): flash('Not authorised') return redirect(url_for('index')) # this is used to update the readme text file form = StudyOverviewForm() # load the study config cfg = dm.config.config() try: cfg.set_study(study.nickname) except KeyError: abort(500) # Get the contents of the study README,md file fro the file system readme_path = os.path.join(cfg.get_study_base(), 'README.md') try: with codecs.open(readme_path, encoding='utf-8', mode='r') as myfile: data = myfile.read() except IOError: data = '' if form.validate_on_submit(): # form has been submitted check for changes # simple MD seems to replace \n with \r\n form.readme_txt.data = form.readme_txt.data.replace('\r', '') # also strip blank lines at the start and end as these are # automatically stripped when the form is submitted if not form.readme_txt.data.strip() == data.strip(): # form has been updated so make a backup anf write back to file timestamp = datetime.datetime.now().strftime('%Y%m%d%H%m') base, ext = os.path.splitext(readme_path) backup_file = base + '_' + timestamp + ext try: shutil.copyfile(readme_path, backup_file) except (IOError, os.error, shutil.Error), why: logger.error( 'Failed to backup readme for study {} with excuse {}'. format(study.nickname, why)) abort(500) with codecs.open(readme_path, encoding='utf-8', mode='w') as myfile: myfile.write(form.readme_txt.data) data = form.readme_txt.data
def session(session_id=None, delete=False, flag_finding=False): """ Default view for a single session_id If called as http://srv-dashboard/session/<session_id>/delete/True it will delete the session from the database """ if session_id is None: return redirect('index') session = Session.query.get(session_id) if not current_user.has_study_access(session.study): flash('Not authorised') return redirect(url_for('index')) try: # Update open issue ID if necessary # this is necessary because GitHub may timeout a user without telling us token = flask_session['active_token'] except: flash('It appears you\'ve been idle too long; please sign in again.') return redirect(url_for('login')) try: # check to see if any issues have been posted on github for this session gh = Github(token) # Due to the way GitHub search API works, splitting session name into separate search terms will find a session # regardless of repeat number, and will not match other sessions with the same study/site open_issues = gh.search_issues( "{} in:title repo:TIGRLab/admin state:open".format( str(session.name).replace("_", " "))) if open_issues.totalCount: session.gh_issue = open_issues[0].number else: session.gh_issue = None db.session.commit() except: flash("Error searching for session's GitHub issue.") if delete: try: if not current_user.is_admin: flash('You dont have permission to do that') raise Exception db.session.delete(session) db.session.commit() flash('Deleted session:{}'.format(session.name)) return redirect( url_for('study', study_id=session.study_id, active_tab='qc')) except Exception: flash('Failed to delete session:{}'.format(session.name)) if flag_finding: try: incident = IncidentalFinding() incident.session_id = session.id incident.user_id = current_user.id db.session.add(incident) db.session.commit() flash('Finding flagged.') return redirect(url_for('session', session_id=session.id)) except: logger.error('Failed flagging finding for session:{}'.format( session.id)) flash('Failed flagging finding. Admins have been notified') studies = current_user.get_studies() form = SessionForm(obj=session) # This form deals with the checklist comments. # Updating the checklist in the database causes checklist.csv to be updated # see models.py scancomment_form = ScanCommentForm() if form.validate_on_submit(): # form has been submitted session.cl_comment = form.cl_comment.data try: db.session.add(session) db.session.commit() flash('Session updated') return redirect( url_for('study', study_id=session.study_id, active_tab='qc')) except SQLAlchemyError as err: logger.error('Session update failed:{}'.format(str(err))) flash('Update failed, admins have been notified, please try again') form.populate_obj(session) return render_template('session.html', studies=studies, study=session.study, session=session, form=form, scancomment_form=scancomment_form)