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)
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"})
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"]
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'}}]})
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"}, )
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
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']
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}'