Example #1
0
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))
Example #2
0
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)))
Example #3
0
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)
Example #4
0
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
Example #5
0
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)
Example #6
0
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
Example #7
0
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)
Example #8
0
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))
Example #9
0
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))
Example #10
0
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
Example #11
0
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)