Esempio n. 1
0
async def setup_server(
    setup_client: AsyncClient,
    editor_client: AsyncClient = None,
    reviewer_client: AsyncClient = None,
):
    await setup_client.create_bucket(
        permissions={
            "collection:create": ["system.Authenticated"],
        },
        if_not_exists=True,
    )
    await setup_client.create_collection(if_not_exists=True)

    if editor_client:
        editor_id = (await editor_client.server_info())["user"]["id"]
        data = JSONPatch([{
            "op": "add",
            "path": "/data/members/0",
            "value": editor_id
        }])
        await setup_client.patch_group(
            id=f"{setup_client.collection_name}-editors", changes=data)

    if reviewer_client:
        reviewer_id = (await reviewer_client.server_info())["user"]["id"]
        data = JSONPatch([{
            "op": "add",
            "path": "/data/members/0",
            "value": reviewer_id
        }])
        await setup_client.patch_group(
            id=f"{setup_client.collection_name}-reviewers", changes=data)
Esempio n. 2
0
async def test_signer_plugin_reviewer_verifications(
    make_client: ClientFactory,
    setup_auth: Auth,
    editor_auth: Auth,
    reviewer_auth: Auth,
    skip_server_setup: bool,
):
    editor_client = make_client(editor_auth)
    reviewer_client = make_client(reviewer_auth)

    if not skip_server_setup:
        setup_client = make_client(setup_auth)
        await setup_server(setup_client, editor_client, reviewer_client)
        # Add reviewer to editors, and vice-versa.
        reviewer_id = (await reviewer_client.server_info())["user"]["id"]
        data = JSONPatch([{
            "op": "add",
            "path": "/data/members/0",
            "value": reviewer_id
        }])
        await setup_client.patch_group(
            id=f"{setup_client.collection_name}-editors", changes=data)
        editor_id = (await editor_client.server_info())["user"]["id"]
        data = JSONPatch([{
            "op": "add",
            "path": "/data/members/0",
            "value": editor_id
        }])
        await setup_client.patch_group(
            id=f"{setup_client.collection_name}-reviewers", changes=data)

    await upload_records(editor_client, 5)

    # status cannot be set to to-sign
    with pytest.raises(KintoException):
        await reviewer_client.patch_collection(data={"status": "to-sign"})

    await reviewer_client.patch_collection(data={"status": "to-review"})
    # same editor cannot review
    with pytest.raises(KintoException):
        await reviewer_client.patch_collection(data={"status": "to-sign"})

    # review must be asked after cancelled
    await editor_client.patch_collection(data={"status": "to-review"})
    await reviewer_client.patch_collection(data={"status": "work-in-progress"})
    with pytest.raises(KintoException):
        await reviewer_client.patch_collection(data={"status": "to-sign"})

    await reviewer_client.patch_collection(data={"status": "to-review"})
    # Client can now review because he is not the last_editor.
    await editor_client.patch_collection(data={"status": "to-sign"})
Esempio n. 3
0
 def test_patch_record_jsonpatch(self):
     self.client.create_bucket(id="b1")
     self.client.create_collection(id="c1", bucket="b1")
     self.client.create_record(id="r1",
                               collection="c1",
                               bucket="b1",
                               data={"hello": "world"})
     patch = JSONPatch([
         {
             "op": "add",
             "path": "/data/goodnight",
             "value": "moon"
         },
         {
             "op": "add",
             "path": "/permissions/read/alice"
         },
     ])
     self.client.patch_record(id="r1",
                              collection="c1",
                              bucket="b1",
                              changes=patch)
     record = self.client.get_record(bucket="b1", collection="c1", id="r1")
     assert record["data"]["hello"] == "world"
     assert record["data"]["goodnight"] == "moon"
     assert record["permissions"]["read"] == ["alice"]
Esempio n. 4
0
    def test_context_manager_works_as_expected(self):
        settings = {"batch_max_requests": 25}
        self.session.request.side_effect = [({"settings": settings}, []),
                                            ({"responses": []}, [])]

        with self.client.batch(bucket='mozilla', collection='test') as batch:
            batch.create_record(id=1234, data={'foo': 'bar'})
            batch.create_record(id=5678, data={'bar': 'baz'})
            batch.patch_record(id=5678, data={'bar': 'biz'})
            changes = JSONPatch([{'op': 'add', 'location': 'foo', 'value': 'bar'}])
            batch.patch_record(id=5678, changes=changes)

        self.session.request.assert_called_with(
            method='POST',
            endpoint='/batch',
            payload={'requests': [
                {'body': {'data': {'foo': 'bar'}},
                 'path': '/buckets/mozilla/collections/test/records/1234',
                 'method': 'PUT',
                 'headers': {'If-None-Match': '*'}},
                {'body': {'data': {'bar': 'baz'}},
                 'path': '/buckets/mozilla/collections/test/records/5678',
                 'method': 'PUT',
                 'headers': {'If-None-Match': '*'}},
                {'body': {'data': {'bar': 'biz'}},
                 'path': '/buckets/mozilla/collections/test/records/5678',
                 'method': 'PATCH',
                 'headers': {'Content-Type': 'application/json'}},
                {'body': [{'op': 'add', 'location': 'foo', 'value': 'bar'}],
                 'path': '/buckets/mozilla/collections/test/records/5678',
                 'method': 'PATCH',
                 'headers': {'Content-Type': 'application/json-patch+json'}}]})
Esempio n. 5
0
    def test_patch_record_understands_jsonpatch(self):
        mock_response(self.session)
        self.client.patch_record(
            bucket='mybucket', collection='mycollection',
            changes=JSONPatch([{'op': 'add', 'patch': '/baz', 'value': 'qux'}]), id=1)

        self.session.request.assert_called_with(
            'patch', '/buckets/mybucket/collections/mycollection/records/1',
            payload=[{'op': 'add', 'patch': '/baz', 'value': 'qux'}],
            headers={"Content-Type": "application/json-patch+json"},
        )
Esempio n. 6
0
    def test_full_review_test(self):
        # Create a collection.
        self.julia_client.create_collection(id="pim")

        # Add Joan to reviewers.
        data = JSONPatch([{
            'op': 'add',
            'path': '/data/members/0',
            'value': self.joan_principal
        }])
        self.julia_client.patch_group(id='reviewers', changes=data)

        # Create some records.
        self.julia_client.create_record(id="abc", collection="pim")
        self.julia_client.create_record(id="def", collection="pim")

        # Preview and prod have no records yet.
        records = self.anon_client.get_records(bucket="preview",
                                               collection="pim")
        assert len(records) == 0
        records = self.anon_client.get_records(bucket="prod", collection="pim")
        assert len(records) == 0

        # Ask for review.
        self.julia_client.patch_collection(id="pim",
                                           data={"status": "to-review"})

        # Preview now has records.
        records = self.anon_client.get_records(bucket="preview",
                                               collection="pim")
        assert len(records) == 2

        # Approve changes.
        self.joan_client.patch_collection(id="pim", data={"status": "to-sign"})

        # Prod now has records.
        records = self.anon_client.get_records(bucket="prod", collection="pim")
        assert len(records) == 2

        # Refresh signature
        self.joan_client.patch_collection(id="pim",
                                          data={"status": "to-resign"})

        # Delete source collection.
        self.julia_client.delete_collection(id="pim")
        records = self.anon_client.get_records(bucket="preview",
                                               collection="pim")
        assert len(records) == 0
        records = self.anon_client.get_records(bucket="prod", collection="pim")
        assert len(records) == 0
Esempio n. 7
0
 def test_patch_record_jsonpatch(self):
     self.client.create_bucket(id='b1')
     self.client.create_collection(id='c1', bucket='b1')
     self.client.create_record(id='r1', collection='c1', bucket='b1',
                               data={"hello": "world"})
     patch = JSONPatch([
         {'op': 'add', 'path': '/data/goodnight', 'value': 'moon'},
         {'op': 'add', 'path': '/permissions/read/alice'}
     ])
     self.client.patch_record(id='r1', collection='c1', bucket='b1',
                              changes=patch)
     record = self.client.get_record(bucket='b1', collection='c1', id='r1')
     assert record['data']['hello'] == 'world'
     assert record['data']['goodnight'] == 'moon'
     assert record['permissions']['read'] == ['alice']
Esempio n. 8
0
async def test_review_signoff(
    base_url: str,
    selenium: WebDriver,
    make_client: ClientFactory,
    setup_auth: Auth,
    editor_auth: Auth,
    reviewer_auth: Auth,
    source_bucket: str,
    source_collection: str,
    skip_server_setup: bool,
    keep_existing: bool,
):
    editor_client = make_client(editor_auth)
    reviewer_client = make_client(reviewer_auth)

    editor_id = (await editor_client.server_info())["user"]["id"]
    reviewer_id = (await reviewer_client.server_info())["user"]["id"]

    # Setup remote server.
    if not skip_server_setup:
        setup_client = make_client(setup_auth)
        await setup_client.create_bucket(if_not_exists=True)
        await setup_client.create_collection(
            permissions={"write": [editor_id, reviewer_id]},
            if_not_exists=True,
        )
        data = JSONPatch([{
            "op": "add",
            "path": "/data/members/0",
            "value": editor_id
        }])
        await setup_client.patch_group(id=f"{source_collection}-editors",
                                       changes=data)
        data = JSONPatch([{
            "op": "add",
            "path": "/data/members/0",
            "value": reviewer_id
        }])
        await setup_client.patch_group(id=f"{source_collection}-reviewers",
                                       changes=data)
        if not keep_existing:
            await setup_client.delete_records()

    dest_bucket = (await
                   signed_resource(editor_client))["destination"]["bucket"]

    # Sample data.
    await editor_client.create_record(data={"testing": 123})
    await editor_client.patch_collection(data={"status": "to-review"})

    # Start browsing.
    selenium.get(base_url)

    sign_in(selenium, reviewer_auth)

    selenium.get(
        base_url +
        f"#/buckets/{source_bucket}/collections/{source_collection}/simple-review"
    )
    selenium.refresh()

    try:
        approve_button: WebElement = selenium.find_element(
            By.XPATH, "//button[contains(., 'Approve')]")
    except NoSuchElementException:
        print(selenium.page_source)  # CI debugging.
        raise

    assert approve_button, "Approve button not found"
    assert approve_button.text == "Approve"
    assert approve_button.is_displayed()

    reject_button: WebElement = selenium.find_element(
        By.XPATH, "//button[contains(., 'Reject')]")
    assert reject_button, "Reject button not found"
    assert reject_button.text == "Reject"
    assert reject_button.is_displayed()

    approve_button.click()

    # find and click show readonly buckets/collections
    readonly_checkbox: WebElement = selenium.find_element(
        By.ID, "read-only-toggle")
    assert readonly_checkbox, "Readonly checkbox not found"
    assert readonly_checkbox.is_displayed()
    readonly_checkbox.click()

    # find and click on main bucket product-integrity collection
    product_integrity: WebElement = selenium.find_element(
        By.XPATH,
        f"//a[@href='#/buckets/{dest_bucket}/collections/{source_collection}/records' and contains(., '{source_collection}')]",
    )
    assert (
        product_integrity
    ), f"{source_collection} collection not found under {dest_bucket} bucket"
    assert product_integrity.is_displayed()
    product_integrity.click()

    # find and ensure record was properly signed to destination bucket
    data: WebElement = selenium.find_element(By.XPATH, "//code")
    assert (
        data
    ), f"Record not found in {source_collection} collection under {dest_bucket} bucket"
    assert data.is_displayed()
    assert data.text == '{"testing":123}'