Exemplo n.º 1
0
def test_change_owner() -> None:
    uuid = str(uuid4())
    alice = User(id=1)
    bob = User(id=2)

    repository = Mock()
    user_service = Mock()
    service = StorageService(
        study_service=Mock(),
        importer_service=Mock(),
        exporter_service=Mock(),
        user_service=user_service,
        repository=repository,
        event_bus=Mock(),
    )

    repository.get.return_value = Study(id=uuid, owner=alice)
    user_service.get_user.return_value = bob

    service.change_owner(
        uuid, 2, RequestParameters(JWTUser(id=1, impersonator=1,
                                           type="users")))
    user_service.get_user.assert_called_once_with(
        2, RequestParameters(JWTUser(id=1, impersonator=1, type="users")))
    repository.save.assert_called_once_with(Study(id=uuid, owner=bob))

    with pytest.raises(UserHasNotPermissionError):
        service.change_owner(
            uuid,
            1,
            RequestParameters(JWTUser(id=1, impersonator=1, type="users")),
        )
def test_server_with_parameters() -> None:

    mock_storage_service = Mock()
    mock_storage_service.get.return_value = {}

    app = Flask(__name__)
    build_storage(
        app,
        storage_service=mock_storage_service,
        session=Mock(),
        config=CONFIG,
        user_service=Mock(),
    )
    client = app.test_client()
    result = client.get("/studies/study1?depth=4")

    parameters = RequestParameters(user=ADMIN)

    assert result.status_code == 200
    mock_storage_service.get.assert_called_once_with("study1", 4, parameters)

    result = client.get("/studies/study2?depth=WRONG_TYPE")

    excepted_parameters = RequestParameters(user=ADMIN)

    assert result.status_code == 200
    mock_storage_service.get.assert_called_with("study2", 3,
                                                excepted_parameters)
Exemplo n.º 3
0
def test_set_public_mode() -> None:
    uuid = str(uuid4())
    group_admin = JWTGroup(id="admin", name="admin", role=RoleType.ADMIN)

    repository = Mock()
    user_service = Mock()
    service = StorageService(
        study_service=Mock(),
        importer_service=Mock(),
        exporter_service=Mock(),
        user_service=user_service,
        repository=repository,
        event_bus=Mock(),
    )

    repository.get.return_value = Study(id=uuid)

    with pytest.raises(UserHasNotPermissionError):
        service.set_public_mode(
            uuid,
            PublicMode.FULL,
            RequestParameters(JWTUser(id=1, impersonator=1, type="users")),
        )

    service.set_public_mode(
        uuid,
        PublicMode.FULL,
        RequestParameters(
            JWTUser(id=1, impersonator=1, type="users", groups=[group_admin])),
    )
    repository.save.assert_called_once_with(
        Study(id=uuid, public_mode=PublicMode.FULL))
Exemplo n.º 4
0
def test_sta_mini_import_output(tmp_path: Path, storage_service) -> None:
    params = RequestParameters(user=ADMIN)

    path_study_output = (storage_service.get_study_path("STA-mini", params) /
                         "output" / "20201014-1422eco-hello")
    sta_mini_output_zip_filepath = shutil.make_archive(tmp_path, "zip",
                                                       path_study_output)

    shutil.rmtree(path_study_output)

    sta_mini_output_zip_path = Path(sta_mini_output_zip_filepath)

    app = Flask(__name__)
    build_storage(
        app,
        storage_service=storage_service,
        session=Mock(),
        user_service=Mock(),
        config=storage_service.study_service.config,
    )
    client = app.test_client()

    study_output_data = io.BytesIO(sta_mini_output_zip_path.read_bytes())
    result = client.post(
        "/studies/STA-mini/output",
        data={"output": (study_output_data, "output.zip")},
    )

    assert result.status_code == HTTPStatus.ACCEPTED.value
Exemplo n.º 5
0
    def get_all_bots() -> Any:
        params = RequestParameters(user=Auth.get_current_user())

        owner = request.args.get("owner", default=None, type=int)
        bots = (service.get_all_bots_by_owner(owner, params)
                if owner else service.get_all_bots(params))
        return jsonify([b.to_dict() for b in bots]), 200
Exemplo n.º 6
0
 def groups_get_id(id: str) -> Any:
     params = RequestParameters(user=Auth.get_current_user())
     group = service.get_group(id, params)
     if group:
         return jsonify(group.to_dict())
     else:
         return f"Group {id} not found", 404
Exemplo n.º 7
0
 def users_get_id(id: int) -> Any:
     params = RequestParameters(user=Auth.get_current_user())
     u = service.get_user(id, params)
     if u:
         return jsonify(u.to_dict())
     else:
         return "", 404
Exemplo n.º 8
0
    def get_file(path: str) -> Any:
        """
        Get file
        ---
        responses:
            '200':
              content:
                application/octet-stream: {}
              description: Successful operation
            '404':
              description: File not found
        parameters:
          - in: path
            name: path
            required: true
            schema:
                type: string
        tags:
          - Manage Matrix

        """

        try:
            params = RequestParameters(user=Auth.get_current_user())
            return storage_service.get_matrix(path, params)
        except FileNotFoundError:
            return f"{path} not found", HTTPStatus.NOT_FOUND.value
    def change_owner(uuid: str, user_id: int) -> Any:
        """
        Change study owner
        ---
        responses:
          '200':
            content:
              application/json: {}
            description: Successful operation
          '400':
            description: Invalid request
        parameters:
          - in: path
            name: uuid
            required: true
            description: study uuid used by server
            schema:
              type: string
          - in: path
            name: user_id
            required: true
            description: id of the new owner
            schema:
              type: number
        tags:
          - Manage Permissions
        """
        uuid_sanitized = sanitize_uuid(uuid)
        params = RequestParameters(user=Auth.get_current_user())
        storage_service.change_owner(uuid_sanitized, user_id, params)

        return "", HTTPStatus.OK
    def set_public_mode(uuid: str, mode: str) -> Any:
        """
        Set study public mode
        ---
        responses:
          '200':
            content:
              application/json: {}
            description: Successful operation
          '400':
            description: Invalid request
        parameters:
          - in: path
            name: uuid
            required: true
            description: study uuid used by server
            schema:
              type: string
          - in: path
            name: mode
            required: true
            description: public mode
            schema:
              type: string
              enum: [NONE,READ,EXECUTE,EDIT,FULL]
        tags:
          - Manage Permissions
        """
        uuid_sanitized = sanitize_uuid(uuid)
        params = RequestParameters(user=Auth.get_current_user())
        public_mode = PublicMode(mode)
        storage_service.set_public_mode(uuid_sanitized, public_mode, params)

        return "", HTTPStatus.OK
    def delete_study(uuid: str) -> Any:
        """
        Delete study
        ---
        responses:
          '200':
            content:
              application/json: {}
            description: Successful operation
          '400':
            description: Invalid request
        parameters:
          - in: path
            name: uuid
            required: true
            description: study uuid used by server
            schema:
              type: string
        tags:
          - Manage Studies
        """
        uuid_sanitized = sanitize_uuid(uuid)

        params = RequestParameters(user=Auth.get_current_user())
        storage_service.delete_study(uuid_sanitized, params)
        content = ""
        code = HTTPStatus.NO_CONTENT.value

        return content, code
    def edit_study(path: str) -> Any:
        """
        Update data
        ---
        responses:
          '200':
            description: Successful operation
            content:
              application/json: {}
          '404':
            description: File not found
        parameters:
          - in: path
            name: uuid
            required: true
            schema:
              type: string
          - in: path
            name: path
            schema:
              type: string
            required: true
        tags:
          - Manage Data inside Study
        """
        new = json.loads(request.data)
        if not new:
            raise BadRequest("empty body not authorized")

        params = RequestParameters(user=Auth.get_current_user())
        storage_service.edit_study(path, new, params)
        content = ""
        code = HTTPStatus.NO_CONTENT.value

        return content, code
Exemplo n.º 13
0
    def post_file(path: str) -> Any:
        """
        Post file
        ---
        parameters:
          - in: path
            name: path
            required: true
            schema:
              type: string
        responses:
          '200':
            content:
              application/json: {}
            description: Successful operation
          '400':
            description: Invalid request
        tags:
          - Manage Matrix
        """

        data = request.files["matrix"].read()
        params = RequestParameters(user=Auth.get_current_user())
        storage_service.upload_matrix(path, data, params)
        output = b""
        code = HTTPStatus.NO_CONTENT.value

        return output, code
    def get_study(path: str) -> Any:
        """
        Read data
        ---
        responses:
          '200':
            description: Successful operation
            content:
              application/json: {}
          '404':
            description: File not found
        parameters:
          - in: path
            name: uuid
            required: true
            schema:
              type: string
          - in: path
            name: path
            schema:
              type: string
            required: true
          - in: query
            name: depth
            schema:
              type: string
        tags:
          - Manage Data inside Study
        """
        parameters = RequestParameters(user=Auth.get_current_user())
        depth = request.args.get("depth", 3, type=int)
        output = storage_service.get(path, depth, parameters)

        return jsonify(output), 200
    def copy_study(uuid: str) -> Any:
        """
        Copy study
        ---
        responses:
          '200':
            content:
              application/json: {}
            description: Successful operation
          '400':
            description: Invalid request
        parameters:
        - in: path
          name: uuid
          required: true
          description: study uuid stored in server
          schema:
            type: string
        - in: query
          name: dest
          required: true
          description: new study name
          schema:
            type: string
        - in: query
          name: groups
          required: false
          description: list of group id assignment separated by comma
          schema:
            type: string
        tags:
          - Manage Studies

        """

        source_uuid = uuid
        destination_study_name = request.args.get("dest")
        groups_arg = request.args.get("groups")
        group_ids = groups_arg.split(",") if groups_arg is not None else []

        if destination_study_name is None:
            content = "Copy operation need a dest query parameter."
            code = HTTPStatus.BAD_REQUEST.value
            return content, code

        source_uuid_sanitized = sanitize_uuid(source_uuid)
        destination_name_sanitized = sanitize_study_name(
            destination_study_name)

        params = RequestParameters(user=Auth.get_current_user())

        destination_uuid = storage_service.copy_study(
            src_uuid=source_uuid_sanitized,
            dest_study_name=destination_name_sanitized,
            group_ids=group_ids,
            params=params,
        )
        code = HTTPStatus.CREATED.value

        return destination_uuid, code
Exemplo n.º 16
0
 def run(study_id: str) -> Any:
     """
     Run study
     ---
     responses:
       '200':
         content:
           application/json:
             schema:
                 $ref: '#/definitions/RunInfo'
         description: Successful operation
       '400':
         description: Invalid request
       '401':
         description: Unauthenticated User
       '403':
         description: Unauthorized
     parameters:
     - in: path
       name: study_id
       required: true
       description: study id
       schema:
         type: string
     definitions:
         - schema:
             id: RunInfo
             properties:
               job_id:
                 type: string
     tags:
       - Run Studies
     """
     params = RequestParameters(user=Auth.get_current_user())
     return jsonify({"job_id": service.run_study(study_id, params)})
Exemplo n.º 17
0
def test_get_studies_uuid() -> None:
    bob = User(id=1, name="bob")
    alice = User(id=2, name="alice")

    a = Study(id="A", owner=bob)
    b = Study(id="B", owner=alice)
    c = Study(id="C", owner=bob)

    # Mock
    repository = Mock()
    repository.get_all.return_value = [a, b, c]

    study_service = Mock()

    service = StorageService(
        study_service=study_service,
        importer_service=Mock(),
        exporter_service=Mock(),
        user_service=Mock(),
        repository=repository,
        event_bus=Mock(),
    )

    studies = service._get_study_metadatas(
        RequestParameters(user=JWTUser(id=1, impersonator=1, type="users")))

    assert [a, c] == studies
    def remove_group(uuid: str, group_id: str) -> Any:
        """
        Remove a group association
        ---
        responses:
          '200':
            content:
              application/json: {}
            description: Successful operation
          '400':
            description: Invalid request
        parameters:
          - in: path
            name: uuid
            required: true
            description: study uuid used by server
            schema:
              type: string
          - in: path
            name: group_id
            required: true
            description: id of the group to remove
            schema:
              type: string
        tags:
          - Manage Permissions
        """
        uuid_sanitized = sanitize_uuid(uuid)

        params = RequestParameters(user=Auth.get_current_user())
        storage_service.remove_group(uuid_sanitized, group_id, params)

        return "", HTTPStatus.OK
Exemplo n.º 19
0
    def users_update(id: int) -> Any:
        params = RequestParameters(user=Auth.get_current_user())
        u = User.from_dict(json.loads(request.data))

        if id != u.id:
            return "Id in path must be same id in body", 400

        return jsonify(service.save_user(u, params).to_dict())
def assert_with_errors(storage_service: StorageService, url: str,
                       new: SUB_JSON) -> None:
    url = url[len("/studies/"):]
    print(url)
    params = RequestParameters(user=ADMIN)
    res = storage_service.edit_study(route=url, new=new, params=params)
    assert res == new

    res = storage_service.get(route=url, depth=-1, params=params)
    assert res == new
Exemplo n.º 21
0
def test_run() -> None:
    job = uuid4()
    study = "my-study"

    service = Mock()
    service.run_study.return_value = job

    app = create_app(service)
    client = app.test_client()
    res = client.post(f"/launcher/run/{study}")

    assert res.status_code == 200
    assert res.json == {"job_id": str(job)}
    service.run_study.assert_called_once_with(study, RequestParameters(ADMIN))
 def get_studies() -> Any:
     """
     Get Studies
     ---
     responses:
       '200':
         content:
           application/json: {}
         description: Successful operation
       '400':
         description: Invalid request
     tags:
       - Manage Studies
     """
     params = RequestParameters(user=Auth.get_current_user())
     available_studies = storage_service.get_studies_information(params)
     return jsonify(available_studies), HTTPStatus.OK.value
Exemplo n.º 23
0
def test_sta_mini_copy(storage_service) -> None:

    source_study_name = "STA-mini"
    destination_study_name = "copy-STA-mini"

    app = Flask(__name__)
    build_storage(
        app,
        session=Mock(),
        user_service=Mock(),
        storage_service=storage_service,
        config=storage_service.study_service.config,
    )
    client = app.test_client()
    result = client.post(
        f"/studies/{source_study_name}/copy?dest={destination_study_name}")

    assert result.status_code == HTTPStatus.CREATED.value
    uuid = result.data.decode("utf-8")

    parameters = RequestParameters(user=ADMIN)
    data_source = storage_service.get(source_study_name, -1, parameters)
    data_destination = storage_service.get(uuid, -1, parameters)

    link_url_source = data_source["input"]["links"]["de"]["fr"]
    assert link_url_source == input_link

    link_url_destination = data_destination["input"]["links"]["de"]["fr"]
    assert link_url_destination == input_link

    def replace_study_name(data: JSON) -> None:
        if isinstance(data, dict):
            for key, value in data.items():
                if isinstance(value, str) and value.startswith("file/"):
                    data[key] = value.replace(uuid, source_study_name)
                else:
                    replace_study_name(value)

    replace_study_name(data_destination)
    del data_source["output"]
    data_source["study"] = {}
    data_destination["study"] = {}

    assert data_source == data_destination
    def export_study(uuid: str) -> Any:
        """
        Export Study
        ---
        responses:
          '200':
            content:
              application/json: {}
            description: Successful operation
          '400':
            description: Invalid request
        parameters:
        - in: path
          name: uuid
          required: true
          description: study uuid stored in server
          schema:
            type: string
        - in: query
          name: no-output
          required: false
          example: false
          description: specify
          schema:
            type: boolean
        tags:
          - Manage Studies
        """
        uuid_sanitized = sanitize_uuid(uuid)
        outputs: bool = ("no-output" not in request.args
                         or request.args["no-output"] == "false")

        params = RequestParameters(user=Auth.get_current_user())
        content = storage_service.export_study(uuid_sanitized, params, outputs)

        return send_file(
            content,
            mimetype="application/zip",
            as_attachment=True,
            attachment_filename=f"{uuid_sanitized}.zip",
        )
Exemplo n.º 25
0
def test_sta_mini_import(tmp_path: Path, storage_service) -> None:

    params = RequestParameters(user=ADMIN)
    path_study = storage_service.get_study_path("STA-mini", params)
    sta_mini_zip_filepath = shutil.make_archive(tmp_path, "zip", path_study)
    sta_mini_zip_path = Path(sta_mini_zip_filepath)

    app = Flask(__name__)
    build_storage(
        app,
        storage_service=storage_service,
        session=Mock(),
        user_service=Mock(),
        config=storage_service.study_service.config,
    )
    client = app.test_client()

    study_data = io.BytesIO(sta_mini_zip_path.read_bytes())
    result = client.post("/studies", data={"study": (study_data, "study.zip")})

    assert result.status_code == HTTPStatus.CREATED.value
    def create_study(name: str) -> Any:
        """
        Create study name
        ---
        description: Create an empty study
        responses:
          '200':
            content:
              application/json: {}
            description: Successful operation
          '400':
            description: Invalid request
        parameters:
          - in: path
            name: name
            required: true
            description: study name asked
            schema:
              type: string
          - in: query
            name: groups
            required: false
            description: list of group id assignment separated by comma
            schema:
              type: string
        tags:
          - Manage Studies
        """
        name_sanitized = sanitize_study_name(name)
        groups_arg = request.args.get("groups")
        group_ids = groups_arg.split(",") if groups_arg is not None else []

        params = RequestParameters(user=Auth.get_current_user())
        uuid = storage_service.create_study(name_sanitized, group_ids, params)

        content = "/studies/" + uuid
        code = HTTPStatus.CREATED.value

        return jsonify(content), code
    def import_study() -> Any:
        """
        Import Study
        ---
        responses:
          '200':
            content:
              application/json: {}
            description: Successful operation
          '400':
            description: Invalid request
        parameters:
        - in: query
          name: groups
          required: false
          description: list of group id assignment separated by comma
          schema:
            type: string
        tags:
          - Manage Studies
        """

        if "study" not in request.files:
            content = "No data provided."
            code = HTTPStatus.BAD_REQUEST.value
            return content, code

        zip_binary = io.BytesIO(request.files["study"].read())

        params = RequestParameters(user=Auth.get_current_user())
        groups_arg = request.args.get("groups")
        group_ids = groups_arg.split(",") if groups_arg is not None else []

        uuid = storage_service.import_study(zip_binary, group_ids, params)
        content = "/studies/" + uuid
        code = HTTPStatus.CREATED.value

        return jsonify(content), code
Exemplo n.º 28
0
 def bots_delete(id: int) -> Any:
     """
     Revoke bot
     ---
     responses:
       '200':
         content:
           application/json: {}
         description: Successful operation
       '400':
         description: Invalid request
     parameters:
       - in: path
         name: id
         required: true
         description: bot id
         schema:
           type: int
     tags:
       - Bot
     """
     params = RequestParameters(user=Auth.get_current_user())
     service.delete_bot(id, params)
     return jsonify(id), 200
    def import_output(uuid: str) -> Any:
        """
        Import Output
        ---
        responses:
          '202':
            content:
              application/json: {}
            description: Successful operation
          '400':
            description: Invalid request
        parameters:
          - in: path
            name: uuid
            required: true
            description: study uuid used by server
            schema:
              type: string
        tags:
          - Manage Outputs
        """
        uuid_sanitized = sanitize_uuid(uuid)

        if "output" not in request.files:
            content = "No data provided."
            code = HTTPStatus.BAD_REQUEST.value
            return content, code

        zip_binary = io.BytesIO(request.files["output"].read())

        params = RequestParameters(user=Auth.get_current_user())
        content = str(
            storage_service.import_output(uuid_sanitized, zip_binary, params))
        code = HTTPStatus.ACCEPTED.value

        return jsonify(content), code
Exemplo n.º 30
0
def assert_with_errors(storage_service: StorageService, url: str,
                       expected_output: dict) -> None:
    url = url[len("/studies/"):]
    params = RequestParameters(user=ADMIN)
    assert (storage_service.get(route=url, depth=3,
                                params=params) == expected_output)