示例#1
0
def download_result_archive(run_id):
    """Download a compressed tar archive containing all result files that were
    generated by a given workflow run.

    NOTE: At this point, the user is not authenticated for file downloads to
    allow download in the GUI via browser redirect.

    Parameters
    ----------
    run_id: string
        Unique run identifier

    Returns
    -------
    flask.response_class

    Raises
    ------
    flowserv.error.UnknownWorkflowGroupError
    """
    from robflask.service import service
    with service() as api:
        ioBuffer = api.runs().get_result_archive(run_id=run_id)
        return send_file(ioBuffer.open(),
                         as_attachment=True,
                         attachment_filename='run.tar.gz',
                         mimetype='application/gzip')
示例#2
0
def client(benchmark_id, tmpdir):
    """Create the app client."""
    # Set the environment variables and create the database.
    connect_url = TEST_DB(tmpdir)
    DB(connect_url=connect_url).init()
    # Create a single benchmark. Need to ensure that the API factory points to
    # the newly created database.
    from robflask.service import init_service
    init_service(basedir=tmpdir, database=connect_url)
    from robflask.service import service
    with service() as api:
        # Get the benchmark repository instance from the API
        api.workflows().create_workflow(identifier=benchmark_id,
                                        name='Hello World',
                                        description='Hello World Demo',
                                        source=BENCHMARK_DIR)
    # Set the maximum upload file size to 1KB
    os.environ[config.ROB_WEBAPI_CONTENTLENGTH] = '1024'
    # Set the UI path.
    os.environ[config.ROB_UI_PATH] = ROB_UI_PATH
    # Create the Flask app
    from robflask.api import create_app
    app = create_app({'TESTING': True})
    with app.test_client() as client:
        yield client
示例#3
0
def delete_run(run_id):
    """Delete the run with the given identifier. The user has to be a member of
    the run submission in order to be authorized to delete the run.

    Parameters
    ----------
    run_id: string
        Unique run identifier

    Returns
    -------
    flask.response_class

    Raises
    ------
    flowserv.error.UnauthenticatedAccessError
    flowserv.error.UnauthorizedAccessError
    flowserv.error.UnknownWorkflowGroupError
    """
    # Get the access token first to raise an error immediately if no token is
    # present (to avoid unnecessarily instantiating the service API).
    from robflask.service import service
    with service(access_token=ACCESS_TOKEN(request)) as api:
        # Authentication of the user from the expected api_token in the header
        # will fail if no token is given or if the user is not logged in.
        api.runs().delete_run(run_id=run_id)
    return make_response(jsonify(dict()), 204)
示例#4
0
def create_submission(workflow_id):
    """Create a new submission for a given benchmark. The user has to be
    authenticated in order to be able to create a new submission.
    """
    # Get the access token first to raise an error immediately if no token is
    # present (to avoid unnecessarily instantiating the service API).
    token = ACCESS_TOKEN(request)
    # Verify that the request contains a valid Json object that contains the
    # submission name and an optional list of member identifier.
    obj = jsonbody(request,
                   mandatory=[labels.GROUP_NAME],
                   optional=[labels.GROUP_MEMBERS])
    name = obj[labels.GROUP_NAME]
    members = obj.get(labels.GROUP_MEMBERS)
    if members is not None and not isinstance(members, list):
        raise err.InvalidRequestError('{} not a list'.format(
            labels.GROUP_MEMBERS))
    from robflask.service import service
    with service(access_token=token) as api:
        # Authentication of the user from the expected api_token in the header
        # will fail if no token is given or if the user is not logged in.
        try:
            r = api.groups().create_group(workflow_id=workflow_id,
                                          name=name,
                                          members=members)
        except UnknownUserError as ex:
            # Change error type from unknown object to invalid request if a
            # user in the member list is unknown
            raise err.InvalidRequestError(str(ex))
    return make_response(jsonify(r), 201)
示例#5
0
def upload_file(group_id):
    """Upload a new file as part of a given submission. The user has to be a
    member of the submission in order to be allowed to upload files.
    """
    # Get the access token first to raise an error immediately if no token is
    # present (to avoid unnecessarily instantiating the service API).
    token = ACCESS_TOKEN(request)
    # Ensure that the upload request contains a file object
    if request.files and 'file' in request.files:
        file = request.files['file']
        # A browser may submit a empty part without filename
        if file.filename == '':
            raise err.InvalidRequestError('empty file name')
        # Save uploaded file to a bytes buffer.
        filename = secure_filename(file.filename)
        from robflask.service import service
        with service(access_token=token) as api:
            # Authentication of the user from the expected api_token in the
            # header will fail if the user is not logged in.
            r = api.uploads().upload_file(group_id=group_id,
                                          file=FlaskFile(file),
                                          name=filename)
        return make_response(jsonify(r), 201)
    else:
        raise err.InvalidRequestError('no file request')
示例#6
0
def download_result_file(run_id, file_id):
    """Download a resource file that was generated by a successful workflow run.
    The user has to be a member of the submission in order to be allowed to
    access files.

    NOTE: At this point, the user is not authenticated for file downloads to
    allow download in the GUI via browser redirect.

    Parameters
    ----------
    run_id: string
        Unique run identifier
    file_id: string
        Unique resource file identifier

    Returns
    -------
    flask.response_class

    Raises
    ------
    flowserv.error.UnauthenticatedAccessError
    flowserv.error.UnauthorizedAccessError
    flowserv.error.UnknownWorkflowGroupError
    """
    print('download {} {}'.format(run_id, file_id))
    from robflask.service import service
    with service() as api:
        # Authentication of the user from the expected api_token in the header
        # will fail if no token is given or if the user is not logged in.
        fh = api.runs().get_result_file(run_id=run_id, file_id=file_id)
        return send_file(fh.open(),
                         as_attachment=True,
                         attachment_filename=fh.name,
                         mimetype=fh.mime_type)
示例#7
0
def register_user():
    """Create a new user. Raises an InvalidRequest object if the request does
    not contain a JSON object with a user name and password for the new user.

    If the request body contains the optional verify flag and if the flag is
    set to False, the user will be activated immediately.

    Returns
    -------
    flask.response_class

    Raises
    ------
    robflask.error.InvalidRequest
    """
    # Verify that the request contains a valid Json object
    obj = jsonbody(request,
                   mandatory=[labels.USER_NAME, labels.USER_PASSWORD],
                   optional=[labels.VERIFY_USER])
    # Get the name and password for the new user and the value of the verify
    # flag. By default the flag is set to True
    user = obj[labels.USER_NAME]
    passwd = obj[labels.USER_PASSWORD]
    if labels.VERIFY_USER in obj:
        verify = bool(obj[labels.VERIFY_USER])
    else:
        verify = True
    # Register user in the database and return the serialized user handle.
    from robflask.service import service
    with service() as api:
        r = api.users().register_user(username=user,
                                      password=passwd,
                                      verify=verify)
    return make_response(jsonify(r), 201)
示例#8
0
def service_descriptor():
    """Get the API service descriptor."""
    # If the request contains an access token we validate that the token is
    # still active. The access token is optional for the service descriptor.
    # Make sure not to raise an error if no token is present.
    from robflask.service import service
    with service(access_token=ACCESS_TOKEN(request, raise_error=False)) as api:
        return jsonify(api.server().to_dict()), 200
示例#9
0
def list_benchmarks():
    """Get listing of available benchmarks. The benchmark listing is available
    to everyone, independent of whether they are currently authenticated or
    not.
    """
    from robflask.service import service
    with service() as api:
        r = api.workflows().list_workflows()
    return make_response(jsonify(r), 200)
示例#10
0
def list_submission(workflow_id):
    """Get a list of all submissions for a given benchmark. The user has to be
    authenticated in order to be able to access the submission list.
    """
    # Get the access token first to raise an error immediately if no token is
    # present (to avoid unnecessarily instantiating the service API).
    from robflask.service import service
    with service(access_token=ACCESS_TOKEN(request)) as api:
        r = api.groups().list_groups(workflow_id=workflow_id)
    return make_response(jsonify(r), 200)
示例#11
0
def get_submission(group_id):
    """Get handle for the submission with the given identifier. The user has to
    be authenticated in order to access a submission.
    """
    # Get the access token first to raise an error immediately if no token is
    # present (to avoid unnecessarily instantiating the service API).
    from robflask.service import service
    with service(access_token=ACCESS_TOKEN(request)) as api:
        r = api.groups().get_group(group_id=group_id)
    return make_response(jsonify(r), 200)
示例#12
0
def delete_submission(group_id):
    """Delete the submission with the given identifier. The user has to be a
    submission member in order to be authorized to delete the submission.
    """
    # Get the access token first to raise an error immediately if no token is
    # present (to avoid unnecessarily instantiating the service API).
    from robflask.service import service
    with service(access_token=ACCESS_TOKEN(request)) as api:
        api.groups().delete_group(group_id=group_id)
    return make_response(jsonify(dict()), 204)
示例#13
0
def get_benchmark(workflow_id):
    """Get handle for given a benchmark. Benchmarks are available to everyone,
    independent of whether they are currently authenticated or not.
    """
    # Get the access token first. Do not raise raise an error if no token is
    # present.
    from robflask.service import service
    with service(access_token=ACCESS_TOKEN(request, raise_error=False)) as api:
        r = api.workflows().get_workflow(workflow_id=workflow_id)
    return make_response(jsonify(r), 200)
示例#14
0
def delete_file(group_id, file_id):
    """Delete a given file that was perviously uploaded for a submission. The
    user has to be a member of the submission in order to be allowed to delete
    files.
    """
    from robflask.service import service
    with service(access_token=ACCESS_TOKEN(request)) as api:
        # Authentication of the user from the expected api_token in the header
        # will fail if no token is given or if the user is not logged in.
        api.uploads().delete_file(group_id=group_id, file_id=file_id)
    return make_response(jsonify(dict()), 204)
示例#15
0
def list_runs(group_id):
    """Get a listing of all runs for a given submission. The user has to be a
    submission member in order to be authorized to list the runs.
    """
    # Get the access token first to raise an error immediately if no token is
    # present (to avoid unnecessarily instantiating the service API).
    from robflask.service import service
    with service(access_token=ACCESS_TOKEN(request)) as api:
        # Authentication of the user from the expected api_token in the header
        # will fail if no token is given or if the user is not logged in.
        r = api.runs().list_runs(group_id=group_id)
    return make_response(jsonify(r), 200)
示例#16
0
def download_benchmark_archive(workflow_id):
    """Download a compressed tar archive containing all current resource files
    for a benchmark that were created during post-processing.
    """
    from robflask.service import service
    with service() as api:
        fh = api.workflows().get_result_archive(workflow_id)
    return send_file(
        fh.open(),
        as_attachment=True,
        attachment_filename='results.tar.gz',
        mimetype='application/gzip'
    )
示例#17
0
def download_file(group_id, file_id):
    """Download a given file that was perviously uploaded for a submission.

    NOTE: At this point, the user is not authenticated for file downloads to
    allow download in the GUI via browser redirect.
    """
    from robflask.service import service
    with service() as api:
        fh = api.uploads().get_uploaded_file_handle(group_id=group_id,
                                                    file_id=file_id)
        return send_file(fh.open(),
                         as_attachment=True,
                         attachment_filename=fh.name,
                         mimetype=fh.mime_type)
示例#18
0
def logout_user():
    """Logout user. Expects an access token for the authenticated user that is
    being logged out.

    Returns
    -------
    flask.response_class

    Raises
    ------
    flowserv.error.UnauthenticatedAccessError
    """
    from robflask.service import service
    with service() as api:
        r = api.users().logout_user(api_key=ACCESS_TOKEN(request))
    return make_response(jsonify(r), 200)
示例#19
0
def request_password_reset():
    """Request to rest the passowrd for a given user.

    Returns
    -------
    flask.response_class
    """
    # Verify that the request contains a valid Json object and get the name of
    # the user whose password is being rest.
    obj = jsonbody(request, mandatory=[labels.USER_NAME])
    user = obj[labels.USER_NAME]
    # Request password reset.
    from robflask.service import service
    with service() as api:
        r = api.users().request_password_reset(username=user)
    return make_response(jsonify(r), 200)
示例#20
0
def get_benchmark_resource(workflow_id, file_id):
    """Download the current resource file for a benchmark resource that was
    created during post-processing.
    """
    from robflask.service import service
    with service() as api:
        fh = api.workflows().get_result_file(
            workflow_id=workflow_id,
            file_id=file_id
        )
        attachment_filename = fh.name
        mimetype = fh.mime_type
    return send_file(
        fh.open(),
        as_attachment=True,
        attachment_filename=attachment_filename,
        mimetype=mimetype
    )
示例#21
0
def list_users():
    """Get listing of registered users. Only users that are registered and
    currently logged in are allowed to query the database.

    Returns
    -------
    flask.response_class

    Raises
    ------
    flowserv.error.UnauthenticatedAccessError
    """
    # Get the access token first to raise an error immediately if no token is
    # present (to avoid unnecessarily instantiating the service API).
    from robflask.service import service
    with service(access_token=ACCESS_TOKEN(request)) as api:
        r = api.users().list_users(query=request.args.get('query'))
    return make_response(jsonify(r), 200)
示例#22
0
def whoami_user():
    """Get information about user that is associated with the provided access
    token.

    Returns
    -------
    flask.response_class

    Raises
    ------
    flowserv.error.UnauthenticatedAccessError
    """
    # Get the access token first to raise an error immediately if no token is
    # present (to avoid unnecessarily instantiating the service API).
    token = ACCESS_TOKEN(request)
    from robflask.service import service
    with service() as api:
        r = api.users().whoami_user(api_key=token)
    return make_response(jsonify(r), 200)
示例#23
0
def activate_user():
    """Activate a newly registered user based on their unique user identifier.

    Returns
    -------
    flask.response_class

    Raises
    ------
    robflask.error.InvalidRequest
    """
    # Verify that the request contains a valid Json object and get the user
    # identifier
    obj = jsonbody(request, mandatory=[labels.USER_ID])
    user_id = obj[labels.USER_ID]
    # Activate user in the database and return the serialized user handle.
    from robflask.service import service
    with service() as api:
        r = api.users().activate_user(user_id=user_id)
    return make_response(jsonify(r), 200)
示例#24
0
def login_user():
    """Authenticate a user based on the given credentials. Returns the access
    token that the user will use in subsequent requests.

    Returns
    -------
    flask.response_class

    Raises
    ------
    robflask.error.InvalidRequest
    """
    # Verify that the request contains a valid Json object
    obj = jsonbody(request, mandatory=[labels.USER_NAME, labels.USER_PASSWORD])
    # Get the name and password for the new user
    user = obj[labels.USER_NAME]
    passwd = obj[labels.USER_PASSWORD]
    # Authenticate user.
    from robflask.service import service
    with service() as api:
        r = api.users().login_user(username=user, password=passwd)
    return make_response(jsonify(r), 200)
示例#25
0
def update_submission(group_id):
    """Update the submission with the given identifier. The request body can
    contain a modified submission name and/or a modified list of submission
    members.
    """
    # Get the access token first to raise an error immediately if no token is
    # present (to avoid unnecessarily instantiating the service API).
    token = ACCESS_TOKEN(request)
    # Verify that the request contains a valid Json object that contains an
    # optional submission name and/or a list of member identifier.
    obj = jsonbody(request,
                   mandatory=[],
                   optional=[labels.GROUP_NAME, labels.GROUP_MEMBERS])
    name = obj.get(labels.GROUP_NAME)
    members = obj.get(labels.GROUP_MEMBERS)
    from robflask.service import service
    with service(access_token=token) as api:
        # Authentication of the user from the expected api_token in the header
        # will fail if no token is given or if the user is not logged in.
        r = api.groups().update_group(group_id=group_id,
                                      name=name,
                                      members=members)
    return make_response(jsonify(r), 200)
示例#26
0
def start_run(group_id):
    """Start a new run. Expects argument values for each mandatory benchmark
    parameter in the request body. The user has to be a submission member in
    order to be authorized to start new submission runs.
    """
    # Get the access token first to raise an error immediately if no token is
    # present (to avoid unnecessarily instantiating the service API).
    token = ACCESS_TOKEN(request)
    # Verify that the request contains a valid Json object that contains a
    # optional list of workflow arguments.
    obj = jsonbody(request, optional=[labels.RUN_ARGUMENTS])
    args = obj[labels.RUN_ARGUMENTS] if labels.RUN_ARGUMENTS in obj else dict()
    from robflask.service import service
    with service(access_token=token) as api:
        # Authentication of the user from the expected api_token in the header
        # will fail if no token is given or if the user is not logged in.
        try:
            r = api.runs().start_run(group_id=group_id, arguments=args)
        except UnknownParameterError as ex:
            # Convert unknown parameter errors into invalid request errors
            # to avoid sending a 404 response
            raise err.InvalidRequestError(str(ex))
    return make_response(jsonify(r), 201)
示例#27
0
def get_leaderboard(workflow_id):
    """Get leader board for a given benchmark. Benchmarks and their results are
    available to everyone, independent of whether they are authenticated or
    not.
    """
    # The orderBy argument can include a list of column names. Each column name
    # may be suffixed by the sort order.
    order_by = request.args.get('orderBy')
    if order_by is not None:
        sort_columns = list()
        for col in order_by.split(','):
            sort_desc = None
            pos = col.find(':')
            if pos > -1:
                if col[pos + 1:].lower() == 'asc':
                    sort_desc = False
                col = col[:pos]
            sort_columns.append(SortColumn(col, sort_desc=sort_desc))
    else:
        sort_columns = None
    # The includeAll argument is a flag. If the argument is given without value
    # the default is True. Otherwise, we expect a string that is equal to true.
    include_all = request.args.get('includeAll')
    if include_all is not None:
        if include_all == '':
            include_all = True
        else:
            include_all = include_all.lower() == 'true'
    # Get serialization of the result ranking
    from robflask.service import service
    with service() as api:
        r = api.workflows().get_ranking(
            workflow_id,
            order_by=sort_columns,
            include_all=include_all
        )
    return make_response(jsonify(r), 200)
示例#28
0
def cancel_run(run_id):
    """Get handle for a given run. The user has to be a member of the run
    submission in order to be authorized to access the run.

    Parameters
    ----------
    run_id: string
        Unique run identifier

    Returns
    -------
    flask.response_class

    Raises
    ------
    flowserv.error.UnauthenticatedAccessError
    flowserv.error.UnauthorizedAccessError
    flowserv.error.UnknownWorkflowGroupError
    """
    # Get the access token first to raise an error immediately if no token is
    # present (to avoid unnecessarily instantiating the service API).
    token = ACCESS_TOKEN(request)
    # If the body contains a Json object verify that the object has the
    # mandatory element 'reason'
    reason = None
    if request.json:
        try:
            obj = util.validate_doc(request.json, mandatory=['reason'])
            reason = obj['reason']
        except ValueError as ex:
            raise err.InvalidRequestError(str(ex))
    from robflask.service import service
    with service(access_token=token) as api:
        # Authentication of the user from the expected api_token in the header
        # will fail if no token is given or if the user is not logged in.
        r = api.runs().cancel_run(run_id=run_id, reason=reason)
    return make_response(jsonify(r), 200)
示例#29
0
def reset_password():
    """Reset the passowrd for a user. The user is identified by the request
    identifier in the request body. This identifier is expected to have been
    generated by a preceeding reset request.

    Returns
    -------
    flask.response_class

    Raises
    ------
    robflask.error.ConstraintViolationError
    """
    # Verify that the request contains a valid Json object
    mandatory_labels = [labels.REQUEST_ID, labels.USER_PASSWORD]
    obj = jsonbody(request, mandatory=mandatory_labels)
    # Get the unique request identifier and the new user password
    req_id = obj[labels.REQUEST_ID]
    passwd = obj[labels.USER_PASSWORD]
    # Reset the password for the user that is identified by the request id.
    from robflask.service import service
    with service() as api:
        r = api.users().reset_password(request_id=req_id, password=passwd)
    return make_response(jsonify(r), 200)