def save_uploaded_file():
    """ Receives files on the server side """
    fchunk = FileChunk.init_from_request()
    logger.info("User uploaded chunk: {}".format(fchunk))
    file_name = fchunk.file_name

    if not fchunk.afile:
        err = utils.pack_error("No file specified.")
        logger.error(err)
        return err

    chunk_path = get_chunk_path(file_name, fchunk.number)

    try:
        # For every request recived we store the chunk to a temp folder
        fchunk.afile.save(chunk_path)
    except Exception as exc:
        logger.error("Problem saving: {} due: {}".format(fchunk, exc))
        return utils.pack_error("Unable to save file chunk: {}"
                                .format(fchunk.number))

    # When all chunks are recived we merge them
    if not all_chunks_received(fchunk):
        return utils.jsonify_success('Request completed successfully.')

    # When all chunks are received we merge them
    subject_file = merge_files(fchunk)

    if subject_file is not None:
        prefix = app.config['REDIDROPPER_UPLOAD_SAVED_DIR']
        file_path = subject_file.get_full_path(prefix)
        delete_temp_files(fchunk)
        hash_matches = verify_file_integrity(fchunk)

        if hash_matches:
            LogEntity.file_uploaded(session['uuid'],
                                    file_path)
            return utils.jsonify_success('File {} uploaded successfully.'
                                         .format(file_name))
        else:
            logger.error("md5 sum does not match for: {}".format(fchunk))
            LogEntity.file_uploaded(session['uuid'],
                                    'Checksum mismatch for file: {}'
                                    .format(file_path))
            return utils.jsonify_error('Checksum mismatch for file: {}'
                                       .format(file_name))
    else:
        LogEntity.file_uploaded(session['uuid'],
                                'Unable to merge chunks for file: {}'
                                .format(file_path))
        return utils.jsonify_error('Unable to merge chunks for file: {}'
                                   .format(file_name))
def save_uploaded_file():
    """ Receives files on the server side """
    fchunk = FileChunk.init_from_request()
    logger.info("User uploaded chunk: {}".format(fchunk))
    file_name = fchunk.file_name

    if not fchunk.afile:
        err = utils.pack_error("No file specified.")
        logger.error(err)
        return err

    chunk_path = get_chunk_path(file_name, fchunk.number)

    try:
        # For every request recived we store the chunk to a temp folder
        fchunk.afile.save(chunk_path)
    except Exception as exc:
        logger.error("Problem saving: {} due: {}".format(fchunk, exc))
        return utils.pack_error("Unable to save file chunk: {}".format(
            fchunk.number))

    # When all chunks are recived we merge them
    if not all_chunks_received(fchunk):
        return utils.jsonify_success('Request completed successfully.')

    # When all chunks are received we merge them
    subject_file = merge_files(fchunk)

    if subject_file is not None:
        prefix = app.config['REDIDROPPER_UPLOAD_SAVED_DIR']
        file_path = subject_file.get_full_path(prefix)
        delete_temp_files(fchunk)
        hash_matches = verify_file_integrity(fchunk)

        if hash_matches:
            LogEntity.file_uploaded(session['uuid'], file_path)
            return utils.jsonify_success(
                'File {} uploaded successfully.'.format(file_name))
        else:
            logger.error("md5 sum does not match for: {}".format(fchunk))
            LogEntity.file_uploaded(
                session['uuid'],
                'Checksum mismatch for file: {}'.format(file_path))
            return utils.jsonify_error(
                'Checksum mismatch for file: {}'.format(file_name))
    else:
        LogEntity.file_uploaded(
            session['uuid'],
            'Unable to merge chunks for file: {}'.format(file_path))
        return utils.jsonify_error(
            'Unable to merge chunks for file: {}'.format(file_name))
示例#3
0
def api_save_user():
    """ Save a new user to the database
    TODO: Add support for reading a password field
    """
    request_data = __extract_user_information(request)
    credentials = __generate_credentials(request_data["email"])
    date_data = __get_date_information()

    if __check_is_existing_user(request_data["email"]):
        return utils.jsonify_error(
            {'message': 'Sorry. This email is already taken.'})

    user = UserEntity.create(email=request_data["email"],
                             first=request_data["first"],
                             last=request_data["last"],
                             minitial=request_data["minitial"],
                             added_at=date_data["added_at"],
                             modified_at=date_data["added_at"],
                             access_expires_at=date_data["access_expires_at"],
                             password_hash="{}:{}"
                             .format(credentials["salt"],
                                     credentials["password_hash"]))

    __assign_roles(request_data["roles"], user)

    app.logger.debug("saved user: {}".format(user))
    LogEntity.account_created(session['uuid'], user)
    return utils.jsonify_success({'user': user.serialize()})
示例#4
0
def find_subject():
    """
    Side effect: This function will synchronize the list of subjects in the
    local database with REDCap by sending a REDCap API call
    if the local database contains no entries.

    :rtype: Response
    :return the list of subjects in json format
    """
    invalid_id = -1

    if 'POST' == request.method:
        search_id = utils.get_safe_int(request.form['name'],
                                       invalid_id, invalid_id)
    else:
        search_id = utils.get_safe_int(request.args.get('name'),
                                       invalid_id,
                                       invalid_id)

    matching = []

    if search_id != invalid_id:
        # @TODO: optimize to return one column by default
        # http://stackoverflow.com/questions/7533146/how-do-i-select-additional-manual-values-along-with-an-sqlalchemy-query
        subject_list = SubjectEntity.query.filter(
            SubjectEntity.redcap_id.like("%{}%".format(search_id))
        ).all()
        matching = [subject.redcap_id for subject in subject_list]

        if len(matching) == 0:
            api_import_redcap_subjects()

    return utils.jsonify_success({'subjects': matching})
示例#5
0
def find_subject():
    """
    :rtype: Response
    :return the list of subjects in json format
    """

    if 'POST' == request.method:
        search_id = request.form['name']
    else:
        search_id = request.args.get('name')

    matching = []

    if search_id is not None:
        # @TODO: optimize to return one column by default
        # http://stackoverflow.com/questions/7533146/how-do-i-select-additional-manual-values-along-with-an-sqlalchemy-query
        subject_list = SubjectEntity.query.filter(
            SubjectEntity.redcap_id.like("%{}%".format(search_id))
        ).all()
        matching = [subject.redcap_id for subject in subject_list]
        # matching = [found for found in matching if search_id in found]
    else:
        app.logger.debug("Invalid API call: "
                         "no value provided for redcap_subject_id.")

    return jsonify_success({'subjects': matching})
示例#6
0
def api_import_redcap_events():
    """
    Refresh the list of events
    """
    url = app.config['REDCAP_API_URL']
    local_events = EventEntity.query.all()
    redcap_events = utils.retrieve_redcap_events(
        url=url,
        token=app.config['REDCAP_API_TOKEN'],
        max_time=app.config['REDCAP_CURL_API_MAX_TIME'])
    new_events = find_new_events(local_events, redcap_events)

    added_date = datetime.today()
    inserted_events = []

    for id, redcap_event in new_events.iteritems():
        evt = EventEntity.create(
            redcap_arm='arm_{}'.format(redcap_event['arm_num']),
            redcap_event=redcap_event['event_name'],
            day_offset=redcap_event['day_offset'],
            added_at=added_date
        )
        inserted_events.append(evt)

    details = [i for i in new_events]
    LogEntity.redcap_events_imported(session['uuid'],
                                     "Total: {} \n {}"
                                     .format(len(details), details))

    return utils.jsonify_success({
        'local_events': [i.get_unique_event_name() for i in local_events],
        'redcap_events': redcap_events,
        'inserted_events': [i.get_unique_event_name() for i in inserted_events],
        'api_url': url})
示例#7
0
def find_subject():
    """
    Side effect: This function will synchronize the list of subjects in the
    local database with REDCap by sending a REDCap API call
    if the local database contains no entries.

    :rtype: Response
    :return the list of subjects in json format
    """
    invalid_id = -1

    if 'POST' == request.method:
        search_id = utils.get_safe_int(request.form['name'], invalid_id,
                                       invalid_id)
    else:
        search_id = utils.get_safe_int(request.args.get('name'), invalid_id,
                                       invalid_id)

    matching = []

    if search_id != invalid_id:
        # @TODO: optimize to return one column by default
        # http://stackoverflow.com/questions/7533146/how-do-i-select-additional-manual-values-along-with-an-sqlalchemy-query
        subject_list = SubjectEntity.query.filter(
            SubjectEntity.redcap_id.like("%{}%".format(search_id))).all()
        matching = [subject.redcap_id for subject in subject_list]

        if len(matching) == 0:
            api_import_redcap_subjects()

    return utils.jsonify_success({'subjects': matching})
示例#8
0
def api_import_redcap_subjects():
    """
    Refresh the list of subjects
    """
    local_subjects = SubjectEntity.query.all()
    url = app.config['REDCAP_API_URL']
    redcap_subjects = utils.retrieve_redcap_subjects(
        url=url,
        token=app.config['REDCAP_API_TOKEN'],
        fields=app.config['REDCAP_DEMOGRAPHICS_SUBJECT_ID'],
        max_time=app.config['REDCAP_CURL_API_MAX_TIME'])
    new_subjects = find_new_subjects(local_subjects, redcap_subjects)

    added_date = datetime.today()
    inserted_subjects = []

    for id, redcap_subject in new_subjects.iteritems():
        subject = SubjectEntity.create(redcap_id=id,
                                       added_at=added_date,
                                       last_checked_at=added_date,
                                       was_deleted=False)
        inserted_subjects.append(subject)

    details = [i for i in new_subjects]
    LogEntity.redcap_subjects_imported(
        session['uuid'], "Total: {} \n {}".format(len(details), details))

    return utils.jsonify_success({
        'local_subjects': [i.redcap_id for i in local_subjects],
        'redcap_subjects':
        redcap_subjects,
        'inserted_subjects': [i.redcap_id for i in inserted_subjects],
        'api_url':
        url
    })
示例#9
0
def find_subject():
    """
    :rtype: Response
    :return the list of subjects in json format
    """

    if 'POST' == request.method:
        search_id = request.form['name']
    else:
        search_id = request.args.get('name')

    matching = []

    if search_id is not None:
        # @TODO: optimize to return one column by default
        # http://stackoverflow.com/questions/7533146/how-do-i-select-additional-manual-values-along-with-an-sqlalchemy-query
        subject_list = SubjectEntity.query.filter(
            SubjectEntity.redcap_id.like("%{}%".format(search_id))).all()
        matching = [subject.redcap_id for subject in subject_list]
        # matching = [found for found in matching if search_id in found]
    else:
        app.logger.debug("Invalid API call: "
                         "no value provided for redcap_subject_id.")

    return jsonify_success({'subjects': matching})
示例#10
0
def api_send_verification_email():
    """
    @TODO: allow POST only
    @TODO: Send Verification Email to user_id

    :rtype: Response
    :return the success or failed in json format
    """
    user_id = get_safe_int(request.form.get('user_id'))
    user = UserEntity.get_by_id(user_id)
    user = UserEntity.get_by_id(1)
    user.email = app.config['MAIL_SENDER_SUPPORT']

    try:
        emails.send_verification_email(user)
        return jsonify_success({"message": "Verification email was sent."})
    except Exception as exc:
        details = "Connection config: {}/{}:{}".format(
            app.config['MAIL_USERNAME'], app.config['MAIL_SERVER'],
            app.config['MAIL_PORT'])
        app.logger.debug(details)
        return jsonify_error({
            "message":
            "Unable to send email due: {} {}".format(exc, details)
        })
示例#11
0
def api_import_redcap_subjects():
    """
    Refresh the list of subjects
    """
    local_subjects = SubjectEntity.query.all()
    url = app.config['REDCAP_API_URL']
    redcap_subjects = utils.retrieve_redcap_subjects(
        url=url,
        token=app.config['REDCAP_API_TOKEN'],
        fields=app.config['REDCAP_DEMOGRAPHICS_SUBJECT_ID'],
        max_time=app.config['REDCAP_CURL_API_MAX_TIME'])
    new_subjects = find_new_subjects(local_subjects, redcap_subjects)

    added_date = datetime.today()
    inserted_subjects = []

    for id, redcap_subject in new_subjects.iteritems():
        subject = SubjectEntity.create(
            redcap_id=id,
            added_at=added_date,
            last_checked_at=added_date,
            was_deleted=False)
        inserted_subjects.append(subject)

    details = [i for i in new_subjects]
    LogEntity.redcap_subjects_imported(session['uuid'],
                                       "Total: {} \n {}"
                                       .format(len(details), details))

    return utils.jsonify_success({
        'local_subjects': [i.redcap_id for i in local_subjects],
        'redcap_subjects': redcap_subjects,
        'inserted_subjects': [i.redcap_id for i in inserted_subjects],
        'api_url': url
    })
示例#12
0
def api_list_subject_events():
    """
    :rtype: Response
    :return the list of subjects in json format
    """
    # from sqlalchemy.sql import text
    from collections import namedtuple

    if 'POST' == request.method:
        subject_id = utils.get_safe_int(request.form.get('subject_id'))
    else:
        subject_id = utils.get_safe_int(request.args.get('subject_id'))

    query = """
SELECT
    evtID AS id
    , evtRedcapArm AS redcap_arm
    , evtRedcapEvent AS redcap_event
    , evtDayOffset AS day_offset
    , COUNT(sfID) AS total_files
    , GROUP_CONCAT(sfFileName) AS file_names
FROM
     Event
    JOIN SubjectFile USING(evtID)
WHERE
    sbjID = :subject_id
GROUP BY
    evtID
    """
    # print subject_id, query
    result = db.session.execute(query, {'subject_id': subject_id})
    Event = namedtuple('Event', result.keys())
    events = [Event(*r) for r in result.fetchall()]
    events_ser = [i._asdict() for i in events]
    return utils.jsonify_success({'subject_events': events_ser})
示例#13
0
def api_list_logs():
    """
    Render the specified page of event logs
    @TODO: show user-specific logs for non-admins?

    :rtype: string
    :return the json list of logs
    """
    if 'POST' == request.method:
        per_page = get_safe_int(request.form.get('per_page'))
        page_num = get_safe_int(request.form.get('page_num'))
    else:
        per_page = get_safe_int(request.args.get('per_page'))
        page_num = get_safe_int(request.args.get('page_num'))

    """
    pagination = LogEntity.query.paginate(page_num, per_page, False)
    items = [i.serialize() for i in pagination.items]
    app.logger.debug("per_page: {}, page_num: {}".format(per_page, page_num))
    return jsonify_success(dict(total_pages=pagination.pages,
                                list_of_events=items))
    """
    logs, total_pages = log_manager.get_logs(per_page, page_num)
    # logs_list = [x.to_visible() for x in logs]
    return jsonify_success(dict(list_of_events=logs, total_pages=total_pages))
示例#14
0
def api_import_redcap_events():
    """
    Refresh the list of events
    """
    url = app.config['REDCAP_API_URL']
    local_events = EventEntity.query.all()
    redcap_events = utils.retrieve_redcap_events(
        url=url,
        token=app.config['REDCAP_API_TOKEN'],
        max_time=app.config['REDCAP_CURL_API_MAX_TIME'])
    new_events = find_new_events(local_events, redcap_events)

    added_date = datetime.today()
    inserted_events = []

    for id, redcap_event in new_events.iteritems():
        evt = EventEntity.create(
            redcap_arm='arm_{}'.format(redcap_event['arm_num']),
            redcap_event=redcap_event['event_name'],
            day_offset=redcap_event['day_offset'],
            added_at=added_date
        )
        inserted_events.append(evt)

    details = [i for i in new_events]
    LogEntity.redcap_events_imported(session['uuid'],
                                     "Total: {} \n {}"
                                     .format(len(details), details))

    return utils.jsonify_success({
        'local_events': [i.get_unique_event_name() for i in local_events],
        'redcap_events': redcap_events,
        'inserted_events': [i.get_unique_event_name() for i in inserted_events],
        'api_url': url})
示例#15
0
def api_list_subject_events():
    """
    :rtype: Response
    :return the list of subjects in json format
    """
    # from sqlalchemy.sql import text
    from collections import namedtuple

    if 'POST' == request.method:
        subject_id = utils.get_safe_int(request.form.get('subject_id'))
    else:
        subject_id = utils.get_safe_int(request.args.get('subject_id'))

    query = """
SELECT
    evtID AS id
    , evtRedcapArm AS redcap_arm
    , evtRedcapEvent AS redcap_event
    , evtDayOffset AS day_offset
    , COUNT(sfID) AS total_files
    , GROUP_CONCAT(sfFileName) AS file_names
FROM
     Event
    JOIN SubjectFile USING(evtID)
WHERE
    sbjID = :subject_id
GROUP BY
    evtID
    """
    # print subject_id, query
    result = db.session.execute(query, {'subject_id': subject_id})
    Event = namedtuple('Event', result.keys())
    events = [Event(*r) for r in result.fetchall()]
    events_ser = [i._asdict() for i in events]
    return utils.jsonify_success({'subject_events': events_ser})
示例#16
0
def api_list_redcap_subjects():
    """
    :rtype: Response
    :return the list of subjects in json format
    """
    subjects = subject_manager.get_fresh_list_of_subjects()
    subjects_list = [x.to_visible() for x in subjects]
    return jsonify_success({'subjects_list': subjects_list})
示例#17
0
def api_list_redcap_subjects():
    """
    :rtype: Response
    :return the list of subjects in json format
    """
    subjects = subject_manager.get_fresh_list_of_subjects()
    subjects_list = [x.to_visible() for x in subjects]
    return jsonify_success({'subjects_list': subjects_list})
示例#18
0
def list_events():
    """
    :rtype: Response
    :return the list of subjects in json format
    """
    # redcap_subject_id = request.form['subject_id']
    # if redcap_subject_id is not None:
    events = EventEntity.query.all()
    events_ser = [i.serialize() for i in events]
    return jsonify_success({'events': events_ser})
示例#19
0
def list_events():
    """
    :rtype: Response
    :return the list of subjects in json format
    """
    # redcap_subject_id = request.form['subject_id']
    # if redcap_subject_id is not None:
    events = EventEntity.query.all()
    events_ser = [i.serialize() for i in events]
    return jsonify_success({'events': events_ser})
示例#20
0
def api_deactivate_account():
    """
    De-activate an user.
    @TODO: should change expiration date too?

    :rtype: Response
    :return the success or failed in json format
    """
    user_id = get_safe_int(request.form.get('user_id'))
    user = UserEntity.get_by_id(user_id)
    user = UserEntity.update(user, active=False)
    return jsonify_success({"message": "User deactivated."})
示例#21
0
def api_deactivate_account():
    """
    De-activate an user.
    @TODO: should change expiration date too?

    :rtype: Response
    :return the success or failed in json format
    """
    user_id = get_safe_int(request.form.get('user_id'))
    user = UserEntity.get_by_id(user_id)
    user = UserEntity.update(user, active=False)
    return jsonify_success({"message": "User deactivated."})
示例#22
0
def api_extend_account():
    """
    Change the `User.usrAccessExpiresAt` to today's date + 180 days

    :rtype: Response
    :return the success or failed in json format
    """
    user_id = request.form.get('user_id')
    today_plus_180 = get_expiration_date(180)
    user = UserEntity.get_by_id(user_id)
    user = UserEntity.update(user, access_expires_at=today_plus_180)
    return jsonify_success(
        {"message": "Updated expiration date to {}".format(today_plus_180)})
示例#23
0
def api_extend_account():
    """
    Change the `User.usrAccessExpiresAt` to today's date + 180 days

    :rtype: Response
    :return the success or failed in json format
    """
    user_id = request.form.get('user_id')
    today_plus_180 = get_expiration_date(180)
    user = UserEntity.get_by_id(user_id)
    user = UserEntity.update(user, access_expires_at=today_plus_180)
    return jsonify_success(
        {"message": "Updated expiration date to {}".format(today_plus_180)})
示例#24
0
def api_save_user():
    """ Save a new user to the database
    TODO: Add support for reading a password field
    """
    email = request.form['email']
    first = request.form['first']
    last = request.form['last']
    minitial = request.form['minitial']
    roles = request.form.getlist('roles[]')

    email_exists = False
    try:
        existing_user = UserEntity.query.filter_by(email=email).one()
        email_exists = existing_user is not None
    except:
        pass

    if email_exists:
        return utils.jsonify_error(
            {'message': 'Sorry. This email is already taken.'})

    # @TODO: use a non-gatorlink password here
    password = email
    salt, password_hash = utils.generate_auth(app.config['SECRET_KEY'],
                                              password)
    added_date = datetime.today()
    access_end_date = utils.get_expiration_date(180)

    # Note: we store the salt as a prefix
    user = UserEntity.create(email=email,
                             first=first,
                             last=last,
                             minitial=minitial,
                             added_at=added_date,
                             modified_at=added_date,
                             access_expires_at=access_end_date,
                             password_hash="{}:{}".format(salt, password_hash))

    user_roles = []
    try:
        for role_name in roles:
            role_entity = RoleEntity.query.filter_by(name=role_name).one()
            user_roles.append(role_entity)
    except Exception as exc:
        app.logger.debug("Problem saving user: {}".format(exc))

    [user.roles.append(rol) for rol in user_roles]
    user = UserEntity.save(user)
    app.logger.debug("saved user: {}".format(user))
    LogEntity.account_created(session['uuid'], user)
    return utils.jsonify_success({'user': user.serialize()})
示例#25
0
def api_save_user():
    """ Save a new user to the database
    TODO: Add support for reading a password field
    """
    email = request.form['email']
    first = request.form['first']
    last = request.form['last']
    minitial = request.form['minitial']
    roles = request.form.getlist('roles[]')

    email_exists = False
    try:
        existing_user = UserEntity.query.filter_by(email=email).one()
        email_exists = existing_user is not None
    except:
        pass

    if email_exists:
        return utils.jsonify_error(
            {'message': 'Sorry. This email is already taken.'})

    # @TODO: use a non-gatorlink password here
    password = email
    salt, password_hash = utils.generate_auth(app.config['SECRET_KEY'],
                                              password)
    added_date = datetime.today()
    access_end_date = utils.get_expiration_date(180)

    # Note: we store the salt as a prefix
    user = UserEntity.create(email=email,
                             first=first,
                             last=last,
                             minitial=minitial,
                             added_at=added_date,
                             modified_at=added_date,
                             access_expires_at=access_end_date,
                             password_hash="{}:{}".format(salt, password_hash))

    user_roles = []
    try:
        for role_name in roles:
            role_entity = RoleEntity.query.filter_by(name=role_name).one()
            user_roles.append(role_entity)
    except Exception as exc:
        app.logger.debug("Problem saving user: {}".format(exc))

    [user.roles.append(rol) for rol in user_roles]
    user = UserEntity.save(user)
    app.logger.debug("saved user: {}".format(user))
    LogEntity.account_created(session['uuid'], user)
    return utils.jsonify_success({'user': user.serialize()})
示例#26
0
def save_uploaded_file():
    """ Receives files on the server side """
    fchunk = FileChunk()
    logger.info("Uploading {}".format(fchunk))

    file_name = fchunk.file_name

    if not utils.allowed_file(file_name):
        err = utils.pack_error("Invalid file type: {}."
                               "Allowed extensions: {}".format(
                                   file_name, utils.ALLOWED_EXTENSIONS))
        logger.error(err)
        return err

    if not fchunk.afile:
        err = utils.pack_error("No file specified.")
        logger.error(err)
        return err

    chunk_path = get_chunk_path(file_name, fchunk.number)

    try:
        # For every request recived we store the chunk to a temp folder
        fchunk.afile.save(chunk_path)
    except:
        logger.error("Problem saving: {}".format(fchunk))
        return utils.pack_error("Unable to save file chunk: {}".format(
            fchunk.number))

    # When all chunks are recived we merge them
    if all_chunks_received(fchunk):
        merge_files(fchunk)
        verify_file_integrity(fchunk)
        delete_temp_files(fchunk)
        return utils.jsonify_success(
            'File {} uploaded successfully.'.format(file_name))
    else:
        return utils.jsonify_success('Request completed successfully.')
def save_uploaded_file():
    """ Receives files on the server side """
    fchunk = FileChunk()
    logger.info("Uploading {}".format(fchunk))

    file_name = fchunk.file_name

    if not utils.allowed_file(file_name):
        err = utils.pack_error("Invalid file type: {}."
                               "Allowed extensions: {}"
                               .format(file_name, utils.ALLOWED_EXTENSIONS))
        logger.error(err)
        return err

    if not fchunk.afile:
        err = utils.pack_error("No file specified.")
        logger.error(err)
        return err

    chunk_path = get_chunk_path(file_name, fchunk.number)

    try:
        # For every request recived we store the chunk to a temp folder
        fchunk.afile.save(chunk_path)
    except:
        logger.error("Problem saving: {}".format(fchunk))
        return utils.pack_error("Unable to save file chunk: {}"
                                .format(fchunk.number))

    # When all chunks are recived we merge them
    if all_chunks_received(fchunk):
        merge_files(fchunk)
        verify_file_integrity(fchunk)
        delete_temp_files(fchunk)
        return utils.jsonify_success('File {} uploaded successfully.'
                                     .format(file_name))
    else:
        return utils.jsonify_success('Request completed successfully.')
示例#28
0
def api_activate_account():
    """
    Activate an user.
    @TODO: should change expiration date too?

    :rtype: Response
    :return the success or failed in json format
    """
    user_id = utils.get_safe_int(request.form.get('user_id'))
    user = UserEntity.get_by_id(user_id)
    user = UserEntity.update(user, active=True)
    LogEntity.account_modified(session['uuid'],
                               "User activated: {}".format(user))
    return utils.jsonify_success({"message": "User activated."})
示例#29
0
def api_expire_account():
    """
    Change the `User.usrAccessExpiresAt` to today's date and 00:00:00 time
    effectively blocking the user access.

    :rtype: Response
    :return the success or failed in json format
    """
    user_id = get_safe_int(request.form.get('user_id'))
    user = UserEntity.get_by_id(user_id)
    today = datetime.today()
    today_start = datetime(today.year, today.month, today.day)
    user = UserEntity.update(user, access_expires_at=today_start)
    return jsonify_success({"message": "User access was expired."})
示例#30
0
def api_expire_account():
    """
    Change the `User.usrAccessExpiresAt` to today's date and 00:00:00 time
    effectively blocking the user access.

    :rtype: Response
    :return the success or failed in json format
    """
    user_id = get_safe_int(request.form.get('user_id'))
    user = UserEntity.get_by_id(user_id)
    today = datetime.today()
    today_start = datetime(today.year, today.month, today.day)
    user = UserEntity.update(user, access_expires_at=today_start)
    return jsonify_success({"message": "User access was expired."})
示例#31
0
def api_activate_account():
    """
    Activate an user.
    @TODO: should change expiration date too?

    :rtype: Response
    :return the success or failed in json format
    """
    user_id = utils.get_safe_int(request.form.get('user_id'))
    user = UserEntity.get_by_id(user_id)
    user = UserEntity.update(user, active=True)
    LogEntity.account_modified(session['uuid'],
                               "User activated: {}".format(user))
    return utils.jsonify_success({"message": "User activated."})
示例#32
0
def api_save_user():
    """ Add New User to the database """
    email = request.form['email']
    first = request.form['first']
    last = request.form['last']
    minitial = request.form['minitial']
    roles = request.form.getlist('roles[]')

    app.logger.debug("roles: {}".format(roles))

    email_exists = False
    try:
        existing_user = UserEntity.query.filter_by(email=email).one()
        email_exists = existing_user is not None
    except:
        pass

    if email_exists:
        return jsonify_error(
            {'message': 'Sorry. This email is already taken.'})

    # @TODO: fix hardcoded values
    # password = '******'
    # salt, hashed_pass = generate_auth(app.config['SECRET_KEY'], password)
    added_date = datetime.today()
    access_end_date = get_expiration_date(180)

    user = UserEntity.create(email=email,
                             first=first,
                             last=last,
                             minitial=minitial,
                             added_at=added_date,
                             modified_at=added_date,
                             access_expires_at=access_end_date,
                             password_hash="")
    # roles=user_roles)
    user_roles = []
    try:
        for role_name in roles:
            role_entity = RoleEntity.query.filter_by(name=role_name).one()
            user_roles.append(role_entity)
    except Exception as exc:
        app.logger.debug("Problem saving user: {}".format(exc))

    [user.roles.append(rol) for rol in user_roles]
    user = UserEntity.save(user)
    app.logger.debug("saved user: {}".format(user))
    return jsonify_success({'user': user.serialize()})
示例#33
0
def list_events():
    """
    Side effect: This function will synchronize the list of events in the
    local database with REDCap by sending a REDCap API call
    if the local database contains no entries.

    :rtype: Response
    :return the list of subjects in json format
    """
    events = EventEntity.query.all()
    events_ser = [i.serialize() for i in events]

    if len(events) == 0:
        api_import_redcap_events()

    return utils.jsonify_success({'events': events_ser})
示例#34
0
def list_events():
    """
    Side effect: This function will synchronize the list of events in the
    local database with REDCap by sending a REDCap API call
    if the local database contains no entries.

    :rtype: Response
    :return the list of subjects in json format
    """
    events = EventEntity.query.all()
    events_ser = [i.serialize() for i in events]

    if len(events) == 0:
        api_import_redcap_events()

    return utils.jsonify_success({'events': events_ser})
示例#35
0
def api_save_user():
    """ Add New User to the database """
    email = request.form['email']
    first = request.form['first']
    last = request.form['last']
    minitial = request.form['minitial']
    roles = request.form.getlist('roles[]')

    app.logger.debug("roles: {}".format(roles))

    email_exists = False
    try:
        existing_user = UserEntity.query.filter_by(email=email).one()
        email_exists = existing_user is not None
    except:
        pass

    if email_exists:
        return jsonify_error({'message': 'Sorry. This email is already taken.'})

    # @TODO: fix hardcoded values
    # password = '******'
    # salt, hashed_pass = generate_auth(app.config['SECRET_KEY'], password)
    added_date = datetime.today()
    access_end_date = get_expiration_date(180)

    user = UserEntity.create(email=email,
                             first=first,
                             last=last,
                             minitial=minitial,
                             added_at=added_date,
                             modified_at=added_date,
                             access_expires_at=access_end_date,
                             password_hash="")
    # roles=user_roles)
    user_roles = []
    try:
        for role_name in roles:
            role_entity = RoleEntity.query.filter_by(name=role_name).one()
            user_roles.append(role_entity)
    except Exception as exc:
        app.logger.debug("Problem saving user: {}".format(exc))

    [user.roles.append(rol) for rol in user_roles]
    user = UserEntity.save(user)
    app.logger.debug("saved user: {}".format(user))
    return jsonify_success({'user': user.serialize()})
示例#36
0
def api_extend_account():
    """
    Change the `User.usrAccessExpiresAt` to today's date + 180 days

    :rtype: Response
    :return the success or failed in json format
    """
    user_id = request.form.get('user_id')
    today_plus_180 = utils.get_expiration_date(180)
    user = UserEntity.get_by_id(user_id)
    user = UserEntity.update(user, access_expires_at=today_plus_180)
    # @TODO: add dedicated log type
    LogEntity.account_modified(
        session['uuid'],
        "Updated expiration date to {}. {}".format(today_plus_180, user.email))
    return utils.jsonify_success(
        {"message": "Updated expiration date to {}".format(today_plus_180)})
示例#37
0
def api_delete_file():
    """ Deletes the passed file    """
    #get the file from the response
    subject_file_id = request.form.get('file_id')

    try:
        ret_value = file_manager.delete_file(subject_file_id)
        deleted_id = ret_value[0]
        deleted_path = ret_value[1]
        app.logger.debug("deleted file id: {}".format(subject_file_id))
        LogEntity.file_deleted(session['uuid'], deleted_path)
        response = utils.jsonify_success({"file_id": deleted_id})

    except:
        response = utils.jsonify_error({"exception": ret_value})

    return response
示例#38
0
def api_expire_account():
    """
    Change the `User.usrAccessExpiresAt` to today's date and 00:00:00 time
    effectively blocking the user access.

    :rtype: Response
    :return the success or failed in json format
    """
    user_id = utils.get_safe_int(request.form.get('user_id'))
    user = UserEntity.get_by_id(user_id)
    today = datetime.today()
    today_start = datetime(today.year, today.month, today.day)
    user = UserEntity.update(user, access_expires_at=today_start)
    # @TODO: add dedicated log type
    LogEntity.account_modified(session['uuid'],
                               "User access was expired. {}".format(user.email))
    return utils.jsonify_success({"message": "User access was expired."})
示例#39
0
def api_extend_account():
    """
    Change the `User.usrAccessExpiresAt` to today's date + 180 days

    :rtype: Response
    :return the success or failed in json format
    """
    user_id = request.form.get('user_id')
    today_plus_180 = utils.get_expiration_date(180)
    user = UserEntity.get_by_id(user_id)
    user = UserEntity.update(user, access_expires_at=today_plus_180)
    # @TODO: add dedicated log type
    LogEntity.account_modified(session['uuid'],
                               "Updated expiration date to {}. {}".format(
                                   today_plus_180, user.email))
    return utils.jsonify_success(
        {"message": "Updated expiration date to {}".format(today_plus_180)})
示例#40
0
def api_expire_account():
    """
    Change the `User.usrAccessExpiresAt` to today's date and 00:00:00 time
    effectively blocking the user access.

    :rtype: Response
    :return the success or failed in json format
    """
    user_id = utils.get_safe_int(request.form.get('user_id'))
    user = UserEntity.get_by_id(user_id)
    today = datetime.today()
    today_start = datetime(today.year, today.month, today.day)
    user = UserEntity.update(user, access_expires_at=today_start)
    # @TODO: add dedicated log type
    LogEntity.account_modified(
        session['uuid'], "User access was expired. {}".format(user.email))
    return utils.jsonify_success({"message": "User access was expired."})
示例#41
0
def api_list_users():
    """
    Retrieve the users cached in the local database
    :rtype: Response
    :return
    """
    if 'POST' == request.method:
        per_page = utils.get_safe_int(request.form.get('per_page'))
        page_num = utils.get_safe_int(request.form.get('page_num'))
    else:
        per_page = utils.get_safe_int(request.args.get('per_page'))
        page_num = utils.get_safe_int(request.args.get('page_num'))

    pagination = UserEntity.query.order_by(
        db.desc(UserEntity.id)).paginate(page_num, per_page, False)
    items = [i.serialize() for i in pagination.items]
    return utils.jsonify_success(
        {"total_pages": pagination.pages, "list_of_users": items})
示例#42
0
def api_list_subject_event_files():
    """
    :rtype: Response
    :return the list of subjects in json format
    """

    if 'POST' == request.method:
        subject_id = utils.get_safe_int(request.form.get('subject_id'))
        event_id = utils.get_safe_int(request.form.get('event_id'))
    else:
        subject_id = utils.get_safe_int(request.args.get('subject_id'))
        event_id = utils.get_safe_int(request.args.get('event_id'))

    files = SubjectFileEntity \
        .query.filter_by(subject_id=subject_id,
                         event_id=event_id).all()
    files_ser = [i.serialize() for i in files]
    return utils.jsonify_success({'subject_event_files': files_ser})
示例#43
0
def api_list_subject_event_files():
    """
    :rtype: Response
    :return the list of subjects in json format
    """

    if 'POST' == request.method:
        subject_id = utils.get_safe_int(request.form.get('subject_id'))
        event_id = utils.get_safe_int(request.form.get('event_id'))
    else:
        subject_id = utils.get_safe_int(request.args.get('subject_id'))
        event_id = utils.get_safe_int(request.args.get('event_id'))

    files = SubjectFileEntity \
        .query.filter_by(subject_id=subject_id,
                         event_id=event_id).all()
    files_ser = [i.serialize() for i in files]
    return utils.jsonify_success({'subject_event_files': files_ser})
示例#44
0
def api_list_users():
    """
    Retrieve the users cached in the local database
    :rtype: Response
    :return
    """
    if 'POST' == request.method:
        per_page = utils.get_safe_int(request.form.get('per_page'))
        page_num = utils.get_safe_int(request.form.get('page_num'))
    else:
        per_page = utils.get_safe_int(request.args.get('per_page'))
        page_num = utils.get_safe_int(request.args.get('page_num'))

    pagination = UserEntity.query.order_by(
        db.desc(UserEntity.id)).paginate(page_num, per_page, False)
    items = [i.serialize() for i in pagination.items]
    return utils.jsonify_success(
        {"total_pages": pagination.pages, "list_of_users": items})
示例#45
0
def api_list_users():
    """
    @TODo: use the page_num in the query
    :rtype: Response
    :return
    """
    if 'POST' == request.method:
        per_page = get_safe_int(request.form.get('per_page'))
        page_num = get_safe_int(request.form.get('page_num'))
    else:
        per_page = get_safe_int(request.args.get('per_page'))
        page_num = get_safe_int(request.args.get('page_num'))

    # users = UserEntity.query.filter(UserEntity.id >= 14).all()
    pagination = UserEntity.query.order_by(
        db.desc(UserEntity.id)).paginate(page_num, per_page, False)
    items = [i.serialize() for i in pagination.items]
    return jsonify_success({"total_pages": pagination.pages,
                            "list_of_users": items})
示例#46
0
def api_list_logs():
    """
    Render the specified page of event logs
    @TODO: show user-specific logs for non-admins?

    :rtype: string
    :return the json list of logs
    """
    if 'POST' == request.method:
        per_page = utils.get_safe_int(request.form.get('per_page'))
        page_num = utils.get_safe_int(request.form.get('page_num'))
    else:
        per_page = utils.get_safe_int(request.args.get('per_page'))
        page_num = utils.get_safe_int(request.args.get('page_num'))

    logs, total_pages = LogEntity.get_logs(per_page, page_num)

    return utils.jsonify_success(
        dict(list_of_events=logs, total_pages=total_pages))
示例#47
0
def api_list_logs():
    """
    Render the specified page of event logs
    @TODO: show user-specific logs for non-admins?

    :rtype: string
    :return the json list of logs
    """
    if 'POST' == request.method:
        per_page = utils.get_safe_int(request.form.get('per_page'))
        page_num = utils.get_safe_int(request.form.get('page_num'))
    else:
        per_page = utils.get_safe_int(request.args.get('per_page'))
        page_num = utils.get_safe_int(request.args.get('page_num'))

    logs, total_pages = LogEntity.get_logs(per_page, page_num)

    return utils.jsonify_success(
        dict(list_of_events=logs, total_pages=total_pages))
示例#48
0
def api_verify_email():
    """
    @TODO: add counter/log to track failed attempts

    :rtype: Response
    :return the success or failed in json format
    """
    if 'POST' == request.method:
        token = utils.clean_str(request.form.get('tok'))
    else:
        token = utils.clean_str(request.args.get('tok'))

    if not token:
        return utils.jsonify_error({'message': 'No token specified.'})

    try:
        email = utils.get_email_from_token(token,
                                           app.config["SECRET_KEY"],
                                           app.config["SECRET_KEY"])
    except Exception as exc:
        # @TODO: add dedicated log type
        app.logger.error("api_verify_email: {}".format(exc.message))
        return utils.jsonify_error({'message': exc.message})

    app.logger.debug("Decoded email from token: {}".format(email))
    user = UserEntity.query.filter_by(email=email).first()

    if user is None:
        app.logger.error("Attempt to verify email with incorrect token: {}"
                         .format(token))
        return utils.jsonify_error({'message': 'Sorry.'})

    user = UserEntity.update(user, email_confirmed_at=datetime.today())
    app.logger.debug("Verified token {} for user {}".format(token, user.email))

    # @TODO: add dedicated log type
    LogEntity.account_modified(session['uuid'],
                               "Verified token {} for user {}".format(
                                   token, user.email))
    return utils.jsonify_success(
        {"message": "Email was verified for {}.".format(email)})
示例#49
0
def api_verify_email():
    """
    @TODO: add counter/log to track failed attempts

    :rtype: Response
    :return the success or failed in json format
    """
    if 'POST' == request.method:
        token = utils.clean_str(request.form.get('tok'))
    else:
        token = utils.clean_str(request.args.get('tok'))

    if not token:
        return utils.jsonify_error({'message': 'No token specified.'})

    try:
        email = utils.get_email_from_token(token,
                                           app.config["SECRET_KEY"],
                                           app.config["SECRET_KEY"])
    except Exception as exc:
        # @TODO: add dedicated log type
        app.logger.error("api_verify_email: {}".format(exc.message))
        return utils.jsonify_error({'message': exc.message})

    app.logger.debug("Decoded email from token: {}".format(email))
    user = UserEntity.query.filter_by(email=email).first()

    if user is None:
        app.logger.error("Attempt to verify email with incorrect token: {}"
                         .format(token))
        return utils.jsonify_error({'message': 'Sorry.'})

    user = UserEntity.update(user, email_confirmed_at=datetime.today())
    app.logger.debug("Verified token {} for user {}".format(token, user.email))

    # @TODO: add dedicated log type
    LogEntity.account_modified(session['uuid'],
                               "Verified token {} for user {}".format(
                                   token, user.email))
    return utils.jsonify_success(
        {"message": "Email was verified for {}.".format(email)})
示例#50
0
def api_list_users():
    """
    @TODo: use the page_num in the query
    :rtype: Response
    :return
    """
    if 'POST' == request.method:
        per_page = get_safe_int(request.form.get('per_page'))
        page_num = get_safe_int(request.form.get('page_num'))
    else:
        per_page = get_safe_int(request.args.get('per_page'))
        page_num = get_safe_int(request.args.get('page_num'))

    # users = UserEntity.query.filter(UserEntity.id >= 14).all()
    pagination = UserEntity.query.order_by(db.desc(UserEntity.id)).paginate(
        page_num, per_page, False)
    items = [i.serialize() for i in pagination.items]
    return jsonify_success({
        "total_pages": pagination.pages,
        "list_of_users": items
    })
示例#51
0
def api_verify_email():
    """
    @TODO: add column for verification hash
    @TODO: add counter/log to track failed attempts

    :rtype: Response
    :return the success or failed in json format
    """
    token = request.form.get('tok')

    # user = UserEntity.query.filter_by(email_token=token).first()
    user = UserEntity.get_by_id(1)

    if user is None:
        app.logger.error("Attempt to verify email with incorrect token: {}"
                         .format(token))
        return jsonify_error({'message': 'Sorry.'})

    app.logger.debug("Verified token {} for user {}".format(token, user.email))
    # implement update User set usrEmailConfirmedAt = NOW()
    return jsonify_success({"message": "Verification email was sent."})
示例#52
0
def api_verify_email():
    """
    @TODO: add column for verification hash
    @TODO: add counter/log to track failed attempts

    :rtype: Response
    :return the success or failed in json format
    """
    token = request.form.get('tok')

    # user = UserEntity.query.filter_by(email_token=token).first()
    user = UserEntity.get_by_id(1)

    if user is None:
        app.logger.error(
            "Attempt to verify email with incorrect token: {}".format(token))
        return jsonify_error({'message': 'Sorry.'})

    app.logger.debug("Verified token {} for user {}".format(token, user.email))
    # implement update User set usrEmailConfirmedAt = NOW()
    return jsonify_success({"message": "Verification email was sent."})
示例#53
0
def api_list_local_subjects():
    """
    Render the table of subjects and their file counts

    @see http://pythonhosted.org/Flask-SQLAlchemy/api.html
        #flask.ext.sqlalchemy.BaseQuery.paginate
    paginate(page, per_page=20, error_out=True)

    :rtype: Response
    :return json
    """
    if 'POST' == request.method:
        per_page = utils.get_safe_int(request.form.get('per_page'))
        page_num = utils.get_safe_int(request.form.get('page_num'))
    else:
        per_page = utils.get_safe_int(request.args.get('per_page'))
        page_num = utils.get_safe_int(request.args.get('page_num'))

    pagination = SubjectEntity.query.paginate(page_num, per_page, False)
    items = [i.serialize() for i in pagination.items]
    return utils.jsonify_success(
        dict(total_pages=pagination.pages, list_of_subjects=items))
示例#54
0
def api_send_verification_email():
    """
    @TODO: Send Verification Email to user_id

    :rtype: Response
    :return the success or failed in json format
    """
    user_id = utils.get_safe_int(request.form.get('user_id'))
    user = UserEntity.get_by_id(user_id)

    try:
        emails.send_verification_email(user)
        return utils.jsonify_success(
            {"message": "Verification email was sent."})
    except Exception as exc:
        details = "Connection config: {}/{}:{}".format(
            app.config['MAIL_USERNAME'],
            app.config['MAIL_SERVER'],
            app.config['MAIL_PORT'])
        app.logger.debug(details)
        return utils.jsonify_error(
            {"message": "Unable to send email due: {} {}".format(exc, details)})
示例#55
0
def api_list_local_subjects():
    """
    Render the table of subjects and their file counts

    @see http://pythonhosted.org/Flask-SQLAlchemy/api.html
        #flask.ext.sqlalchemy.BaseQuery.paginate
    paginate(page, per_page=20, error_out=True)

    :rtype: Response
    :return json
    """
    if 'POST' == request.method:
        per_page = utils.get_safe_int(request.form.get('per_page'))
        page_num = utils.get_safe_int(request.form.get('page_num'))
    else:
        per_page = utils.get_safe_int(request.args.get('per_page'))
        page_num = utils.get_safe_int(request.args.get('page_num'))

    pagination = SubjectEntity.query.paginate(page_num, per_page, False)
    items = [i.serialize() for i in pagination.items]
    return utils.jsonify_success(
        dict(total_pages=pagination.pages, list_of_subjects=items))
示例#56
0
def api_edit_user():
    """ Edit an existing user in the database
    TODO: Add support for reading a password field
    """
    request_data = __extract_user_information(request)
    credentials = __generate_credentials(request_data["email"])
    date_data = __get_date_information()

    user = UserEntity.get_by_id(id=request_data["usr_id"])
    user.update(email=request_data["email"],
                first=request_data["first"],
                last=request_data["last"],
                minitial=request_data["minitial"],
                added_at=date_data["added_at"],
                modified_at=date_data["added_at"],
                access_expires_at=date_data["access_expires_at"],
                password_hash="{}:{}".format(credentials["salt"],
                                             credentials["password_hash"]))

    __assign_roles(request_data["roles"], user)

    app.logger.debug("updated user: {}".format(user))
    LogEntity.account_updated(session['uuid'], user)
    return utils.jsonify_success({'user': user.serialize()})
示例#57
0
def api_list_logs():
    """
    Render the specified page of event logs
    @TODO: show user-specific logs for non-admins?

    :rtype: string
    :return the json list of logs
    """
    if 'POST' == request.method:
        per_page = get_safe_int(request.form.get('per_page'))
        page_num = get_safe_int(request.form.get('page_num'))
    else:
        per_page = get_safe_int(request.args.get('per_page'))
        page_num = get_safe_int(request.args.get('page_num'))
    """
    pagination = LogEntity.query.paginate(page_num, per_page, False)
    items = [i.serialize() for i in pagination.items]
    app.logger.debug("per_page: {}, page_num: {}".format(per_page, page_num))
    return jsonify_success(dict(total_pages=pagination.pages,
                                list_of_events=items))
    """
    logs, total_pages = log_manager.get_logs(per_page, page_num)
    # logs_list = [x.to_visible() for x in logs]
    return jsonify_success(dict(list_of_events=logs, total_pages=total_pages))