Пример #1
0
async def test_update_job_script_bad_permission(
    client,
    fill_application_data,
    fill_job_script_data,
    inject_security_header,
):
    """
    Test that it is not possible to update a job_script if the user don't have the proper permission.

    This test proves that it is not possible to update a job_script if the user don't have permission. We
    show this by asserting that the response status code of the request is 403, and that the data stored in
    the database for the job_script is not updated.
    """
    inserted_application_id = await database.execute(
        query=applications_table.insert(),
        values=fill_application_data(application_owner_email="*****@*****.**"),
    )
    await database.execute(
        query=job_scripts_table.insert(),
        values=fill_job_script_data(job_script_name="target-js",
                                    application_id=inserted_application_id),
    )

    inject_security_header("*****@*****.**", "INVALID_PERMISSION")
    response = await client.put("/jobbergate/job-scripts/1",
                                data={"job_script_name": "new name"})

    assert response.status_code == status.HTTP_403_FORBIDDEN

    query = job_scripts_table.select(
        job_scripts_table.c.job_script_name == "target-js")
    job_script_row = await database.fetch_one(query)

    assert job_script_row is not None
    assert job_script_row["job_script_name"] == "target-js"
Пример #2
0
async def job_script_list(
    pagination: Pagination = Depends(),
    all: Optional[bool] = Query(False),
    search: Optional[str] = Query(None),
    sort_field: Optional[str] = Query(None),
    sort_ascending: bool = Query(True),
    token_payload: TokenPayload = Depends(
        guard.lockdown(Permissions.JOB_SCRIPTS_VIEW)),
):
    """
    List job_scripts for the authenticated user.

    Note::

       Use responses instead of response_model to skip a second round of validation and serialization. This
       is already happening in the ``package_response`` method. So, we uses ``responses`` so that FastAPI
       can generate the correct OpenAPI spec but not post-process the response.
    """
    query = job_scripts_table.select()
    identity_claims = IdentityClaims.from_token_payload(token_payload)
    if not all:
        query = query.where(job_scripts_table.c.job_script_owner_email ==
                            identity_claims.user_email)
    if search is not None:
        query = query.where(search_clause(search, searchable_fields))
    if sort_field is not None:
        query = query.order_by(
            sort_clause(sort_field, sortable_fields, sort_ascending))
    return await package_response(JobScriptResponse, query, pagination)
async def job_submission_create(
    job_submission: JobSubmissionCreateRequest,
    token_payload: TokenPayload = Depends(
        guard.lockdown(Permissions.JOB_SUBMISSIONS_EDIT)),
):
    """
    Create a new job submission.

    Make a post request to this endpoint with the required values to create a new job submission.
    """
    identity_claims = IdentityClaims.from_token_payload(token_payload)
    cluster_id = job_submission.cluster_id or identity_claims.cluster_id
    if cluster_id is None:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=
            "Could not find a cluster_id in the request body or auth token.",
        )

    create_dict = dict(
        **job_submission.dict(exclude_unset=True),
        job_submission_owner_email=identity_claims.user_email,
        status=JobSubmissionStatus.CREATED,
    )
    if job_submission.cluster_id is None:
        create_dict.update(cluster_id=cluster_id)

    exec_dir = create_dict.pop("execution_directory", None)
    if exec_dir is not None:
        create_dict.update(execution_directory=str(exec_dir))

    select_query = job_scripts_table.select().where(
        job_scripts_table.c.id == job_submission.job_script_id)
    raw_job_script = await database.fetch_one(select_query)

    if not raw_job_script:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"JobScript id={job_submission.job_script_id} not found.",
        )

    async with database.transaction():
        try:
            insert_query = job_submissions_table.insert().returning(
                job_submissions_table)
            job_submission_data = await database.fetch_one(query=insert_query,
                                                           values=create_dict)

        except INTEGRITY_CHECK_EXCEPTIONS as e:
            raise HTTPException(
                status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
                detail=str(e))

    return job_submission_data
Пример #4
0
async def test_update_job_script(
    client,
    fill_application_data,
    fill_job_script_data,
    inject_security_header,
    time_frame,
):
    """
    Test update job_script via PUT.

    This test proves that the job_script values are correctly updated following a PUT request to the
    /job-scripts/<id> endpoint. We show this by assert the response status code to 201, the response data
    corresponds to the updated data, and the data in the database is also updated.
    """
    inserted_application_id = await database.execute(
        query=applications_table.insert(),
        values=fill_application_data(application_owner_email="*****@*****.**"),
    )
    inserted_job_script_id = await database.execute(
        query=job_scripts_table.insert(),
        values=fill_job_script_data(application_id=inserted_application_id),
    )

    inject_security_header("*****@*****.**", Permissions.JOB_SCRIPTS_EDIT)
    with time_frame() as window:
        response = await client.put(
            f"/jobbergate/job-scripts/{inserted_job_script_id}",
            json={
                "job_script_name": "new name",
                "job_script_description": "new description",
                "job_script_data_as_string": "new value",
            },
        )

    assert response.status_code == status.HTTP_200_OK
    data = response.json()

    assert data["job_script_name"] == "new name"
    assert data["job_script_description"] == "new description"
    assert data["job_script_data_as_string"] == "new value"
    assert data["id"] == inserted_job_script_id

    query = job_scripts_table.select(
        job_scripts_table.c.id == inserted_job_script_id)
    job_script = JobScriptResponse.parse_obj(await database.fetch_one(query))

    assert job_script is not None
    assert job_script.job_script_name == "new name"
    assert job_script.job_script_description == "new description"
    assert job_script.job_script_data_as_string == "new value"
    assert job_script.updated_at in window
Пример #5
0
async def job_script_get(job_script_id: int = Query(...)):
    """
    Return the job_script given its id.
    """
    query = job_scripts_table.select().where(
        job_scripts_table.c.id == job_script_id)
    job_script = await database.fetch_one(query)

    if not job_script:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"JobScript with id={job_script_id} not found.",
        )
    return job_script
Пример #6
0
async def job_script_delete(job_script_id: int = Query(
    ..., description="id of the job script to delete")):
    """
    Delete job_script given its id.
    """
    where_stmt = job_scripts_table.c.id == job_script_id

    get_query = job_scripts_table.select().where(where_stmt)
    raw_job_script = await database.fetch_one(get_query)
    if not raw_job_script:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"JobScript with id={job_script_id} not found.",
        )

    delete_query = job_scripts_table.delete().where(where_stmt)
    await database.execute(delete_query)