def test_dataset_elements_creation(self): """ Factory can create multiple dataset's elements at once. """ creator = TokenDAO("normal user privileged with link", 1, 3, "user1", privileges=Privileges.CREATE_DATASET + Privileges.ADD_ELEMENTS ) dataset = DatasetDAO("user1/dataset1", "example_dataset", "dataset for testing purposes", "none", tags=["example", "0"]) self.session.flush() creator = creator.link_dataset(dataset) # Creator can create elements into the dataset elements_kwargs = [ dict(title="New element", description="Description unknown", tags=["example_tag"], content=b"hello"), dict(title="New element2", description="Description unknown2", tags=["example_tag2"], content=b"hello2"), dict(title="New element3", description="Description unknown3", tags=["example_tag3"], content=b"hello3"), ] elements = DatasetElementFactory(creator, dataset).create_elements(elements_kwargs) self.assertEqual(len(elements), 3) content = storage.get_file(elements[0].file_ref_id).content self.assertEqual(content, b"hello") content = storage.get_file(elements[1].file_ref_id).content self.assertEqual(content, b"hello2") content = storage.get_file(elements[2].file_ref_id).content self.assertEqual(content, b"hello3") dataset = dataset.update() self.assertEqual(len(dataset.elements), 3)
def test_dataset_elements_info_by_pages(self): """ Factory can retrieve multiple elements at once by pages. """ editor = TokenDAO("normal user privileged with link", 1, 5, "user1", privileges=Privileges.RO_WATCH_DATASET ) dataset = DatasetDAO("user1/dataset1", "example_dataset", "dataset for testing purposes", "none", tags=["example", "0"]) self.session.flush() editor = editor.link_dataset(dataset) elements = [DatasetElementDAO("example{}".format(x), "none", None, dataset=dataset).title for x in range(5)] self.session.flush() dataset = dataset.update() page_size = global_config.get_page_size() for page in range(len(elements) // page_size + int(len(elements) % page_size > 0)): retrieved_elements = DatasetElementFactory(editor, dataset).get_elements_info(page) for x in retrieved_elements: self.assertIn(x.title, elements)
def test_dataset_multiple_elements_content_retrieval(self): """ Factory can retrieve content of multiple elements at once. """ editor = TokenDAO("normal user privileged with link", 1, 1, "user1", privileges=Privileges.RO_WATCH_DATASET ) dataset = DatasetDAO("user1/dataset1", "example_dataset", "dataset for testing purposes", "none", tags=["example", "0"]) self.session.flush() editor = editor.link_dataset(dataset) file_id1 = storage.put_file_content(b"content1") file_id2 = storage.put_file_content(b"content2") element = DatasetElementDAO("example1", "none", file_id1, dataset=dataset) element2 = DatasetElementDAO("example2", "none", file_id1, dataset=dataset) element3 = DatasetElementDAO("example3", "none", file_id2, dataset=dataset) self.session.flush() dataset = dataset.update() with self.assertRaises(RequestedRangeNotSatisfiable) as ex: contents = DatasetElementFactory(editor, dataset).get_elements_content([element._id, element2._id, element3._id]) contents = DatasetElementFactory(editor, dataset).get_elements_content([element._id, element3._id]) self.assertEqual(contents[element._id], b"content1") self.assertEqual(contents[element3._id], b"content2")
def test_factory_can_get_tokens(self): """ Factory can retrieve tokens. """ token = TokenDAO("example1", 5, 5, "uri1") token2 = TokenDAO("example2", 5, 5, "uri2") token3 = TokenDAO("example3", 5, 5, "uri2", privileges=Privileges.USER_EDIT_TOKEN) token4 = TokenDAO("example3", 5, 5, "uri2", privileges=Privileges.ADMIN_EDIT_TOKEN) self.session.flush() new_token = TokenFactory(token).get_token(token.token_gui) self.assertEqual(token.token_gui, new_token.token_gui) self.assertEqual(token.description, new_token.description) self.assertEqual(token.url_prefix, new_token.url_prefix) # Cannot request info from a different token with self.assertRaises(Unauthorized): new_token = TokenFactory(token).get_token(token2.token_gui) # Cannot request all the tokens if not privileged. with self.assertRaises(Unauthorized): new_token = TokenFactory(token).get_tokens() # Can request all the tokens if has privilege for user edit tokens. token_list = TokenFactory(token3).get_tokens() self.assertEqual(len(token_list), 3) # Can not request all the tokens from a different url prefix with self.assertRaises(Unauthorized): token_list = TokenFactory(token3).get_tokens(url_prefix="uri1") # Admin can request tokens from all the url prefixes token_list = TokenFactory(token4).get_tokens() self.assertEqual(len(token_list), 4) token_list = TokenFactory(token4).get_tokens(url_prefix="uri1") self.assertEqual(len(token_list), 1) token_list = TokenFactory(token4).get_tokens(url_prefix="uri2") self.assertEqual(len(token_list), 3) token_list = TokenFactory(token4).get_tokens(url_prefix="UNKNOWN") self.assertEqual(len(token_list), 0) # Invalid token-GUI raises exception with self.assertRaises(BadRequest): token_list = TokenFactory(token4).get_token( token_gui="INVALID_GUI")
def test_dataset_fork(self): """ Factory can fork a dataset :return: """ viewer = TokenDAO("normal user only view dataset", 2, 10, "viewer", privileges=Privileges.RO_WATCH_DATASET) creator = TokenDAO("normal user privileged", 2, 10, "creator", privileges=Privileges.CREATE_DATASET) d = DatasetDAO("viewer/dataset", "dataset", "description for dataset", "none", ["d1", "d2"]) self.session.flush() element1 = DatasetElementDAO("a", "a", None, "noneaa", ["taga"], dataset=d) element2 = DatasetElementDAO("b", "b", None, "nonebb", ["tagb"], dataset=d) self.session.flush() d = d.update() self.assertEqual(len(d.elements), 2) viewer = viewer.link_dataset(d) d.update() # Creator can clone it from viewer. forked_dataset = DatasetFactory(creator).fork_dataset(d.url_prefix, viewer, title="dataset_cloned", url_prefix="dataset", description="desc", reference="none", tags=["d2", "d1"]) self.assertEqual(forked_dataset.url_prefix, "creator/dataset") self.assertEqual(forked_dataset.title, "dataset_cloned") self.assertEqual(forked_dataset.description, "desc") self.assertEqual(forked_dataset.tags, ["d2", "d1"]) self.assertEqual(len(forked_dataset.elements), 2) elements_titles = [element1.title, element2.title] self.assertIn(forked_dataset.elements[0].title, elements_titles) self.assertIn(forked_dataset.elements[1].title, elements_titles) # viewer can NOT clone it from creator. with self.assertRaises(Unauthorized) as ex: forked_dataset = DatasetFactory(viewer).fork_dataset(forked_dataset.url_prefix, creator, title="dataset_cloned", url_prefix="dataset", description="desc", reference="none", tags=["d2", "d1"]) # Dataset can be forked omitting some options forked_dataset2 = DatasetFactory(creator).fork_dataset(d.url_prefix, viewer, url_prefix="dataset2") self.assertEqual(forked_dataset2.title, d.title) self.assertEqual(forked_dataset2.description, d.description) self.assertEqual(forked_dataset2.tags, d.tags) self.assertEqual(forked_dataset2.reference, d.reference)
def test_clone_element(self): """ Factory can clone elements. """ editor = TokenDAO("normal user privileged with link", 2, 1, "user1", privileges=Privileges.RO_WATCH_DATASET + Privileges.EDIT_DATASET + Privileges.ADD_ELEMENTS ) dataset = DatasetDAO("user1/dataset1", "example_dataset", "dataset for testing purposes", "none", tags=["example", "0"]) dataset2 = DatasetDAO("user1/dataset2", "example_dataset2", "dataset2 for testing purposes", "none", tags=["example", "1"]) self.session.flush() editor = editor.link_dataset(dataset) file_id1 = storage.put_file_content(b"content1") file_id2 = storage.put_file_content(b"content2") element = DatasetElementDAO("example1", "none", file_id1, dataset=dataset) element2 = DatasetElementDAO("example2", "none", file_id1, dataset=dataset) element3 = DatasetElementDAO("example3", "none", file_id2, dataset=dataset) self.session.flush() dataset = dataset.update() dataset2 = dataset2.update() self.assertEqual(len(dataset.elements), 3) self.assertEqual(len(dataset2.elements), 0) with self.assertRaises(Unauthorized) as ex: new_element = DatasetElementFactory(editor, dataset).clone_element(element._id, dataset2.url_prefix) editor = editor.link_dataset(dataset2) self.assertEqual(len(element.dataset_id), 1) new_element = DatasetElementFactory(editor, dataset).clone_element(element._id, dataset2.url_prefix) dataset2 = dataset2.update() self.assertEqual(len(dataset2.elements), 1) self.assertEqual(new_element.file_ref_id, element.file_ref_id) self.assertEqual(new_element.title, element.title) self.assertEqual(new_element.description, element.description) self.assertEqual(new_element.tags, element.tags) self.assertEqual(new_element._id, element._id) self.assertEqual(len(new_element.dataset_id), 2) self.assertEqual(len(element.dataset_id), 2) with self.assertRaises(Unauthorized) as ex: new_element = DatasetElementFactory(editor, dataset).clone_element(element2._id, dataset2.url_prefix)
def test_token_can_be_created_and_destroyed(self): """ Tests that tokens are successfully created and removed. :return: """ token = TokenDAO("example", 2, 3, "dalap") token_gui = token.token_gui self.assertTrue(len(token.token_gui) > 10) self.session.flush() token = TokenDAO.query.get(token_gui=token_gui) self.assertEqual(token.token_gui, token_gui) token.delete() token = TokenDAO.query.get(token_gui) self.assertIsNone(token)
def testDatasetCreationLimit(self): """ Factory limits creation of dataset depending on the token used to create it. """ creator = TokenDAO("normal user privileged", 1, 1, "user1", privileges=Privileges.CREATE_DATASET) # Creator should not be able to create more than 1 dataset dataset1 = DatasetFactory(creator).create_dataset(url_prefix="creator", title="Creator dataset", description="Dataset example creator", reference="Unknown") creator = creator.link_dataset(dataset1) self.session.flush() with self.assertRaises(Unauthorized) as ex: dataset2 = DatasetFactory(creator).create_dataset(url_prefix="creator2", title="Creator dataset2", description="Dataset2 example creator", reference="Unknown")
def test_factory_can_delete_tokens(self): """ Factory can remove tokens. :return: """ token = TokenDAO("example1", 5, 5, "uri1") token_demo1 = TokenDAO("example2", 5, 5, "uri1") token_demo2 = TokenDAO("exampleN", 5, 5, "uri2") token3 = TokenDAO("example3", 5, 5, "uri2", privileges=Privileges.USER_DESTROY_TOKEN) token4 = TokenDAO("example4", 5, 5, "uri2", privileges=Privileges.ADMIN_DESTROY_TOKEN) self.session.flush() # Unauthorized token can't delete tokens on same url_prefix with self.assertRaises(Unauthorized) as ex: TokenFactory(token).delete_token(token_demo1.token_gui) # Unauthorized token can't delete tokens on other url_prefix with self.assertRaises(Unauthorized) as ex: TokenFactory(token).delete_token(token_demo2.token_gui) # Unauthorized token can't delete himself with self.assertRaises(Unauthorized) as ex: TokenFactory(token_demo1).delete_token(token_demo1.token_gui) # Authorized token can't delete other's tokens with self.assertRaises(Unauthorized) as ex: TokenFactory(token3).delete_token(token_demo1.token_gui) # Authorized token can't delete admin tokens with self.assertRaises(Unauthorized) as ex: TokenFactory(token3).delete_token(token4.token_gui) # Authorized token can delete token on same uri prefix TokenFactory(token3).delete_token(token_demo2.token_gui) # Authorized token can delete itself TokenFactory(token3).delete_token(token3.token_gui) # Admin token can delete anything TokenFactory(token4).delete_token(token_demo1.token_gui)
def test_dataset_modification(self): """ Factory can modify datasets :return: """ dataset = DatasetDAO("foo/hello", "notitle", "desc", "ref") dataset2 = DatasetDAO("bar/hello", "notitle", "desc", "ref") token_unprivileged = TokenDAO("unprivileged", 0, 0, "bar") token_privileged = TokenDAO("privileged", 0, 0, "bar", privileges=Privileges.EDIT_DATASET) token_admin = TokenDAO("admin", 0, 0, "bar", privileges=Privileges.ADMIN_EDIT_TOKEN) self.session.flush() # Unprivileged token cannot modify dataset with self.assertRaises(Unauthorized) as ex: DatasetFactory(token_unprivileged).edit_dataset(dataset.url_prefix, title="hello") # Privileged token cannot modify dataset if not in same url prefix with self.assertRaises(Unauthorized) as ex: DatasetFactory(token_privileged).edit_dataset(dataset.url_prefix, title="hello") # Privileged token can modify dataset if in same url prefix # NOT: Because dataset is not linked with the token. with self.assertRaises(Unauthorized) as ex: dataset2 = DatasetFactory(token_privileged).edit_dataset(dataset2.url_prefix, title="hello") # If we link it, then it does: token_privileged = token_privileged.link_dataset(dataset2) dataset2 = DatasetFactory(token_privileged).edit_dataset(dataset2.url_prefix, title="hello") self.assertEqual(dataset2.title, "hello") # Admin token can modify any dataset dataset = DatasetFactory(token_admin).edit_dataset(dataset.url_prefix, title="hello2") self.assertEqual(dataset.title, "hello2") # Privileged can partially modify url prefix dataset2 = DatasetFactory(token_privileged).edit_dataset(dataset2.url_prefix, url_prefix="new_prefix") self.assertEqual(dataset2.url_prefix, "bar/new_prefix") with self.assertRaises(BadRequest) as ex: dataset2 = DatasetFactory(token_privileged).edit_dataset(dataset2.url_prefix, url_prefix="bar2/new_prefix") # Admin can modify url prefix without problems dataset2 = DatasetFactory(token_admin).edit_dataset(dataset2.url_prefix, url_prefix="bar2/new_prefix") self.assertEqual(dataset2.url_prefix, "bar2/new_prefix")
def test_dataset_elements_removal(self): """ Factory can remove mutliple elements from datasets at once. """ destructor = TokenDAO("normal user privileged with link", 1, 1, "user1", privileges=Privileges.DESTROY_DATASET + Privileges.DESTROY_ELEMENTS ) dataset = DatasetDAO("user1/dataset1", "example_dataset", "dataset for testing purposes", "none", tags=["example", "0"]) self.session.flush() destructor = destructor.link_dataset(dataset) file_id1 = storage.put_file_content(b"content1") file_id2 = storage.put_file_content(b"content2") element = DatasetElementDAO("example1", "none", file_id1, dataset=dataset) element2 = DatasetElementDAO("example2", "none", file_id1, dataset=dataset) element3 = DatasetElementDAO("example3", "none", file_id2, dataset=dataset) self.session.flush() dataset = dataset.update() self.assertEqual(len(dataset.elements), 3) with self.assertRaises(RequestedRangeNotSatisfiable) as ex: DatasetElementFactory(destructor, dataset).destroy_elements([element._id, element2._id, element3._id]) DatasetElementFactory(destructor, dataset).destroy_elements([element._id, element2._id]) dataset = dataset.update() self.assertEqual(len(dataset.elements), 1) self.assertEqual(dataset.elements[0]._id, element3._id) element = DatasetElementDAO("example1", "none", file_id1, dataset=dataset) element2 = DatasetElementDAO("example2", "none", file_id1, dataset=dataset) self.session.flush() dataset = dataset.update() DatasetElementFactory(destructor, dataset).destroy_elements()
def test_dataset_specific_elements_info(self): """ Factory can retrieve multiple elements at once by specific sets. """ editor = TokenDAO("normal user privileged with link", 1, 1, "user1", privileges=Privileges.RO_WATCH_DATASET ) dataset = DatasetDAO("user1/dataset1", "example_dataset", "dataset for testing purposes", "none", tags=["example", "0"]) self.session.flush() editor = editor.link_dataset(dataset) elements = [DatasetElementDAO("example{}".format(x), "none", None, dataset=dataset) for x in range(5)] titles = [element.title for element in elements] ids = [element._id for element in elements] self.session.flush() dataset = dataset.update() # Can't retrieve more elements than the page size at once. with self.assertRaises(RequestedRangeNotSatisfiable) as ex: retrieved_elements = [x for x in DatasetElementFactory(editor, dataset).get_specific_elements_info(ids)] request1 = ids[0:2] retrieved_elements = [x for x in DatasetElementFactory(editor, dataset).get_specific_elements_info(request1)] self.assertEqual(len(retrieved_elements), 2) self.assertIn(retrieved_elements[0].title, titles) self.assertIn(retrieved_elements[1].title, titles) request2 = ids[1:3] retrieved_elements2 = [x for x in DatasetElementFactory(editor, dataset).get_specific_elements_info(request2)] self.assertEqual(len(retrieved_elements2), 2) self.assertIn(retrieved_elements2[0].title, titles) self.assertIn(retrieved_elements2[1].title, titles) self.assertNotEqual(retrieved_elements[0].title, retrieved_elements2[0].title) self.assertNotEqual(retrieved_elements[1].title, retrieved_elements2[1].title) self.assertEqual(retrieved_elements[1].title, retrieved_elements2[0].title)
def test_dataset_elements_edit(self): """ Factory can edit multiple elements from datasets at once. """ editor = TokenDAO("normal user privileged with link", 1, 1, "user1", privileges=Privileges.EDIT_DATASET + Privileges.EDIT_ELEMENTS ) dataset = DatasetDAO("user1/dataset1", "example_dataset", "dataset for testing purposes", "none", tags=["example", "0"]) self.session.flush() editor = editor.link_dataset(dataset) file_id1 = storage.put_file_content(b"content1") file_id2 = storage.put_file_content(b"content2") element = DatasetElementDAO("example1", "none", file_id1, dataset=dataset) element2 = DatasetElementDAO("example2", "none", file_id1, dataset=dataset) element3 = DatasetElementDAO("example3", "none", file_id2, dataset=dataset) self.session.flush() dataset = dataset.update() self.assertEqual(len(dataset.elements), 3) modifications = { element._id: dict(title="asd6", content=b"content4"), element3._id: dict(description="ffff", content=b"New Content!") } DatasetElementFactory(editor, dataset).edit_elements(modifications) self.session.flush() dataset = dataset.update() element = element.update() element3 = element3.update() self.assertEqual(element.title, "asd6") self.assertEqual(storage.get_file(element.file_ref_id).content, b"content4") self.assertEqual(element3.description, "ffff") self.assertEqual(storage.get_file(element3.file_ref_id).content, b"New Content!")
def test_dataset_elements_info_by_different_pages_size(self): """ Factory can retrieve multiple elements with different page sizes. """ initial_page_size = global_config.get_page_size() global_config.set_page_size(10) editor = TokenDAO("normal user privileged with link", 1, 5, "user1", privileges=Privileges.RO_WATCH_DATASET ) dataset = DatasetDAO("user1/dataset1", "example_dataset", "dataset for testing purposes", "none", tags=["example", "0"]) self.session.flush() editor = editor.link_dataset(dataset) elements = [DatasetElementDAO("example{}".format(x), "none", None, dataset=dataset).title for x in range(5)] self.session.flush() dataset = dataset.update() # We need to know the order of the elements ordered_elements = [l for l in DatasetElementFactory(editor, dataset).get_elements_info(page_size=len(elements))] pages_size = [1, 2, 3, 4, 5] for page_size in pages_size: num_pages = len(elements) // page_size + int(len(elements) % page_size > 0) for page in range(num_pages): retrieved_elements = [l for l in DatasetElementFactory(editor, dataset).get_elements_info(page, page_size=page_size)] for retrieved_element, ordered_element in zip(retrieved_elements, ordered_elements[page*page_size:(page+1)*page_size]): self.assertEqual(retrieved_element._id, ordered_element._id) with self.assertRaises(Conflict): retrieved_elements = DatasetElementFactory(editor, dataset).get_elements_info(page_size=global_config.get_page_size()+1) global_config.set_page_size(initial_page_size)
def test_dataset_element_creation_limit(self): """ Factory limits creation of dataset's elements depending on the token used to create it. """ creator = TokenDAO("normal user privileged", 1, 1, "user1", privileges=Privileges.CREATE_DATASET+Privileges.ADD_ELEMENTS) dataset = DatasetDAO("user1/dataset1", "example_dataset", "dataset for testing purposes", "none", tags=["example", "0"]) self.session.flush() # Creator should not be able to create more than 1 element in any dataset creator = creator.link_dataset(dataset) element1 = DatasetElementFactory(creator, dataset).create_element(title="New element1", description="Description unknown", tags=["example_tag"], content=b"hello") dataset = dataset.update() with self.assertRaises(Unauthorized) as ex: element2 = DatasetElementFactory(creator, dataset).create_element(title="New element2", description="Description unknown", tags=["example_tag"], content=b"hello")
def test_dataset_creation(self): """ Factory can create datasets :return: """ anonymous = TokenDAO("Anonymous", 1, 1, "anonymous") watcher = TokenDAO("normal user", 1, 1, "user1") creator = TokenDAO("normal user privileged", 1, 1, "user1", privileges=Privileges.CREATE_DATASET) admin = TokenDAO("admin user", 1, 1, "admin", privileges=Privileges.ADMIN_CREATE_TOKEN + Privileges.ADMIN_EDIT_TOKEN + Privileges.ADMIN_DESTROY_TOKEN) # Anonymous or watcher can't create datasets with self.assertRaises(Unauthorized) as ex: dataset = DatasetFactory(anonymous).create_dataset(url_prefix="anonymous", title="Anonymous dataset", description="Dataset example anonymous", reference="Unknown") with self.assertRaises(Unauthorized) as ex: dataset = DatasetFactory(watcher).create_dataset(url_prefix="watcher", title="Watcher dataset", description="Dataset example watcher", reference="Unknown") # Creator can create a dataset dataset = DatasetFactory(creator).create_dataset(url_prefix="creator", title="Creator dataset", description="Dataset example creator", reference="Unknown") self.assertEqual(join_prefixes(creator.url_prefix, "creator"), dataset.url_prefix) self.assertEqual(dataset.description, "Dataset example creator") # Not all prefixes allowed (for example, "/" char is protected) illegal_chars = "/*;:,.ç´`+Ǩ^><¿?'¡¿!\"·$%&/()@~¬" for illegal_char in illegal_chars: with self.assertRaises(BadRequest) as ex: dataset = DatasetFactory(creator).create_dataset(url_prefix="creator{}da".format(illegal_char), title="Creator dataset", description="Dataset example creator", reference="Unknown") # Admin can create dataset dataset = DatasetFactory(admin).create_dataset(url_prefix="admin", title="Admin dataset", description="Dataset example admin", reference="Unknown") self.assertEqual(join_prefixes(admin.url_prefix, "admin"), dataset.url_prefix) self.assertEqual(dataset.description, "Dataset example admin") # Admin can create dataset on other's url prefixes dataset = DatasetFactory(admin).create_dataset(url_prefix="user1/admin", title="Admin dataset", description="Dataset example admin", reference="Unknown") self.assertEqual(join_prefixes(creator.url_prefix, "admin"), dataset.url_prefix) self.assertEqual(dataset.description, "Dataset example admin")
def test_dataset_retrieval(self): """ Factory can retrieve datasets. :return: """ anonymous = TokenDAO("Anonymous", 1, 1, "anonymous") watcher = TokenDAO("normal user", 1, 1, "user1", privileges=0) creator = TokenDAO("normal user privileged", 1, 1, "user1", privileges=Privileges.CREATE_DATASET) creator2 = TokenDAO("normal user privileged", 1, 1, "user2", privileges=Privileges.CREATE_DATASET) admin = TokenDAO("admin user", 1, 1, "admin", privileges=Privileges.ADMIN_CREATE_TOKEN + Privileges.ADMIN_EDIT_TOKEN + Privileges.ADMIN_DESTROY_TOKEN) dataset = DatasetFactory(creator).create_dataset(url_prefix="creator", title="Creator dataset", description="Dataset example creator", reference="Unknown") dataset2 = DatasetFactory(creator2).create_dataset(url_prefix="creator", title="Creator dataset", description="Dataset example creator", reference="Unknown") self.session.flush() # anonymous should not be able to get info from the dataset with self.assertRaises(Unauthorized) as ex: dataset3 =DatasetFactory(anonymous).get_dataset(dataset.url_prefix) # watcher should not be able to get info from the dataset with self.assertRaises(Unauthorized) as ex: dataset3 =DatasetFactory(watcher).get_dataset(dataset.url_prefix) # creator should not be able to get info from the dataset with self.assertRaises(Unauthorized) as ex: dataset3 =DatasetFactory(creator).get_dataset(dataset.url_prefix) # admin should be able to get info from the dataset dataset3 =DatasetFactory(admin).get_dataset(dataset.url_prefix) self.assertEqual(dataset3.url_prefix, dataset.url_prefix) anonymous = anonymous.link_dataset(dataset) # anonymous should now be able to get info from the dataset dataset3 =DatasetFactory(anonymous).get_dataset(dataset.url_prefix) self.assertEqual(dataset3.url_prefix, dataset.url_prefix) # The privilege RO_WATCH_DATASET is always required except for admin watcher = watcher.link_dataset(dataset) with self.assertRaises(Unauthorized) as ex: dataset3 =DatasetFactory(watcher).get_dataset(dataset.url_prefix)
def create_token(self, *args, **kwargs): kwargs = dict(kwargs) can_create_others = bool(self.token.privileges & Privileges.ADMIN_CREATE_TOKEN) can_create_all_inner_tokens = bool(self.token.privileges & Privileges.USER_CREATE_TOKEN) if "url_prefix" in kwargs: url_prefix = kwargs["url_prefix"] del kwargs["url_prefix"] else: url_prefix = args[3] if not can_create_others: if "privileges" in kwargs: privileges = kwargs["privileges"] # We need to check privileges creation. An exploit would be to allow creation of tokens with highest privileges # from non-trusted tokens. if not self._compatible_privileges(self.token.privileges, privileges): abort(409, message= "This token can't create such privileged tokens.") if not can_create_all_inner_tokens: abort( 401, message="This token can't create such privileged tokens.") if url_prefix != self.token.url_prefix: abort( 401, message= "This token can't create tokens outside of its url prefix." ) kwargs["url_prefix"] = url_prefix token = TokenDAO(*args, **kwargs) self.session.flush() return token
def test_dataset_destruction(self): """ Factory can destroy datasets :return: """ anonymous = TokenDAO("Anonymous", 1, 1, "anonymous") watcher = TokenDAO("normal user", 1, 1, "user1") creator = TokenDAO("normal user privileged", 1, 1, "user1", privileges=Privileges.CREATE_DATASET) creator2 = TokenDAO("normal user privileged", 1, 1, "user2", privileges=Privileges.CREATE_DATASET) destructor = TokenDAO("normal user privileged", 1, 1, "user1", privileges=Privileges.DESTROY_DATASET) admin = TokenDAO("admin user", 1, 1, "admin", privileges=Privileges.ADMIN_CREATE_TOKEN + Privileges.ADMIN_EDIT_TOKEN + Privileges.ADMIN_DESTROY_TOKEN) dataset = DatasetFactory(creator).create_dataset(url_prefix="creator", title="Creator dataset", description="Dataset example creator", reference="Unknown") dataset2 = DatasetFactory(creator2).create_dataset(url_prefix="creator", title="Creator dataset", description="Dataset example creator", reference="Unknown") self.session.flush() # Anonymous or watcher can't destroy datasets with self.assertRaises(Unauthorized) as ex: DatasetFactory(anonymous).destroy_dataset(url_prefix="user1/creator") with self.assertRaises(Unauthorized) as ex: DatasetFactory(watcher).destroy_dataset(url_prefix="user1/creator") # creator can't destroy a dataset with self.assertRaises(Unauthorized) as ex: DatasetFactory(creator).destroy_dataset(url_prefix="user1/creator") # destructor can't destroy other's datasets with self.assertRaises(Unauthorized) as ex: DatasetFactory(destructor).destroy_dataset(url_prefix="user2/creator") # destructor can destroy within his url-prefix datasets DatasetFactory(destructor).destroy_dataset(url_prefix="user1/creator") self.session.flush() self.session.clear() dataset = DatasetDAO.query.get(url_prefix="user1/creator") self.assertIsNone(dataset, None) # destructor can destroy within any url-prefix datasets DatasetFactory(admin).destroy_dataset(url_prefix="user2/creator") self.session.flush() self.session.clear() dataset = DatasetDAO.query.get(url_prefix="user2/creator") self.assertIsNone(dataset, None)
def test_token_can_link_datasets(self): """ Tests that tokens can be associated to multiple datasets and disassociated. :return: """ token1 = TokenDAO("example_token", 2, 5, "dalap") token2 = TokenDAO("example_token2", 2, 5, "dalap") dataset1 = DatasetDAO("ex/ivan", "example1", "lalala", "none") dataset2 = DatasetDAO("ex/ivan2", "example2", "lalala", "none") token1 = token1.link_datasets([dataset1, dataset2]) token2 = token2.link_dataset(dataset2) self.session.flush() self.assertEqual(len(token1.datasets), 2) self.assertEqual(len(token2.datasets), 1) token1 = token1.unlink_dataset(dataset2) self.assertEqual(len(token1.datasets), 1)
def __create_token__(namespace, description, max_datasets, max_elements_per_dataset, privileges, duration_in_days, end_date=None): illegal_chars = "/*;:,.ç´`+Ǩ^><¿?'¡¿!\"·$%&()@~¬" if any([i in namespace for i in illegal_chars]): print("[ERROR] The namespace can't hold any of the following chars:\n\"{}\"".format(illegal_chars)) exit(-1) from mldatahub.odm.dataset_dao import DatasetDAO from mldatahub.odm.token_dao import TokenDAO if end_date is not None: end_date = end_date else: end_date = now()+relativedelta(days=+duration_in_days) token = TokenDAO(description=description, max_dataset_count=max_datasets, max_dataset_size=max_elements_per_dataset, url_prefix=namespace, end_date=end_date, privileges=privileges) global_config.get_session().flush() return token
def test_factory_creation_token(self): """ Factory can create tokens. :return: """ token = TokenDAO("example1", 5, 5, "url1") token2 = TokenDAO("example3", 5, 5, "url2", privileges=Privileges.USER_CREATE_TOKEN + Privileges.RO_WATCH_DATASET) token3 = TokenDAO("example3", 5, 5, "url2", privileges=Privileges.ADMIN_CREATE_TOKEN) # Unprivileged token should not be able to create new tokens with self.assertRaises(Unauthorized) as ex: new_token = TokenFactory(token).create_token( description="example1", max_dataset_count=4, max_dataset_size=4, url_prefix="url1") # Privileged token should be able to create new tokens in his prefix new_token = TokenFactory(token2).create_token(description="example2", max_dataset_count=4, max_dataset_size=4, url_prefix="url2") self.assertEqual(new_token.url_prefix, "url2") self.assertEqual(new_token.description, "example2") # Privileged token should be not able to create new tokens out of his prefix with self.assertRaises(Unauthorized) as ex: new_token = TokenFactory(token2).create_token( description="example3", max_dataset_count=4, max_dataset_size=4, url_prefix="url1") # Admin token should be able to create new tokens in his prefix new_token = TokenFactory(token3).create_token(description="example4", max_dataset_count=4, max_dataset_size=4, url_prefix="url2") self.assertEqual(new_token.url_prefix, "url2") self.assertEqual(new_token.description, "example4") # Admin token should be able to create new tokens out of his prefix new_token = TokenFactory(token3).create_token(description="example5", max_dataset_count=4, max_dataset_size=4, url_prefix="url1") self.assertEqual(new_token.url_prefix, "url1") self.assertEqual(new_token.description, "example5") # Privileged token should not be able to create new tokens out of his privilege set. with self.assertRaises(Conflict) as ex: new_token = TokenFactory(token2).create_token( description="example6", max_dataset_count=4, max_dataset_size=4, url_prefix="url2", privileges=Privileges.ADMIN_CREATE_TOKEN) # Privileged token can create tokens with its privilege set. new_token = TokenFactory(token2).create_token( description="example7", max_dataset_count=4, max_dataset_size=4, url_prefix="url2", privileges=Privileges.USER_CREATE_TOKEN) self.assertEqual(new_token.url_prefix, "url2") self.assertEqual(new_token.description, "example7") # Admin token can create tokens with any privilege set. new_token = TokenFactory(token3).create_token( description="example8", max_dataset_count=4, max_dataset_size=4, url_prefix="url1", privileges=Privileges.ADD_ELEMENTS + Privileges.DESTROY_DATASET + Privileges.ADMIN_CREATE_TOKEN) self.assertEqual(new_token.description, "example8") self.assertEqual(new_token.url_prefix, "url1") self.assertEqual( new_token.privileges, Privileges.ADD_ELEMENTS + Privileges.DESTROY_DATASET + Privileges.ADMIN_CREATE_TOKEN)
def test_dataset_can_be_unlinked_with_token(self): """ Factory can unlink datasets. :return: """ token = TokenDAO("linker", 1, 1, "testinglink", privileges=Privileges.RO_WATCH_DATASET + Privileges.CREATE_DATASET) token2 = TokenDAO("linker", 1, 1, "testinglink2", privileges=Privileges.RO_WATCH_DATASET + Privileges.USER_EDIT_TOKEN) token21 = TokenDAO("linker", 1, 1, "testinglink2", privileges=Privileges.RO_WATCH_DATASET + Privileges.USER_EDIT_TOKEN) dataset = DatasetDAO("{}/{}".format(token.url_prefix, "dataset"), "dataset1", "dataset example", "none") dataset2 = DatasetDAO("{}/{}".format(token2.url_prefix, "dataset2"), "dataset2", "dataset example2", "none") token3 = TokenDAO("linked", 1, 1, "testinglink2", privileges=Privileges.RO_WATCH_DATASET + Privileges.ADMIN_EDIT_TOKEN) self.session.flush() token = token.link_datasets([dataset, dataset2]) token21 = token21.link_datasets([dataset2]) # Not privileged token can't link a dataset. with self.assertRaises(Unauthorized) as ex: token21 = TokenFactory(token).unlink_datasets( token21.token_gui, [dataset2.url_prefix]) with self.assertRaises(Unauthorized) as ex: token = TokenFactory(token).unlink_datasets( token.token_gui, [dataset.url_prefix]) # Privileged token can unlink a dataset. token21 = TokenFactory(token2).unlink_datasets(token21.token_gui, [dataset2.url_prefix]) self.assertEqual(len(token21.datasets), 0) token21 = token21.link_datasets([dataset]) # Privileged token can NOT unlink a dataset of other url prefix with self.assertRaises(Unauthorized) as ex: token21 = TokenFactory(token2).unlink_datasets( token21.token_gui, [dataset.url_prefix]) # Privileged token can NOT unlink a dataset from a token of other url prefix with self.assertRaises(Unauthorized) as ex: token = TokenFactory(token2).unlink_datasets( token.token_gui, [dataset.url_prefix]) # Admin can do all of the above cases. token21 = TokenFactory(token3).unlink_datasets(token21.token_gui, [dataset.url_prefix]) token = TokenFactory(token3).unlink_datasets(token.token_gui, [dataset.url_prefix]) self.assertEqual(len(token21.datasets), 0) self.assertEqual(len(token.datasets), 1)
def test_factory_can_modify_tokens(self): """ Factory can modify tokens depending on privileges of main token. :return: """ token = TokenDAO("example1", 5, 5, "uri1") token2 = TokenDAO("example2", 5, 5, "uri2") token3 = TokenDAO("example3", 5, 5, "uri2", privileges=Privileges.USER_EDIT_TOKEN) token4 = TokenDAO("example3", 5, 5, "uri2", privileges=Privileges.ADMIN_EDIT_TOKEN) self.session.flush() # token is not allowed to change token2 with self.assertRaises(Unauthorized): new_token = TokenFactory(token).edit_token( token_gui=token2.token_gui, description="New description") # token3 should be allowed to change token2 new_token = TokenFactory(token3).edit_token( token_gui=token2.token_gui, description="New description") self.assertEqual(token2.token_gui, new_token.token_gui) self.assertEqual("New description", new_token.description) self.assertEqual("uri2", new_token.url_prefix) # token4 should be allowed to change token2 new_token = TokenFactory(token4).edit_token( token_gui=token2.token_gui, description="New description2") self.assertEqual(token2.token_gui, new_token.token_gui) self.assertEqual("New description2", new_token.description) self.assertEqual("uri2", new_token.url_prefix) # token is not allowed to change itself with self.assertRaises(Unauthorized): new_token = TokenFactory(token).edit_token( token_gui=token.token_gui, description="New description") # Non valid token GUI should raise exception with self.assertRaises(BadRequest): new_token = TokenFactory(token).edit_token( token_gui="INVALID", description="New description") # Token3 should not be able to change url prefix with self.assertRaises(Unauthorized): new_token = TokenFactory(token3).edit_token( token_gui=token2.token_gui, url_prefix="new_prefix") # However, Token4 should be able to change url prefix new_token = TokenFactory(token4).edit_token(token_gui=token2.token_gui, url_prefix="new_prefix") self.assertEqual("new_prefix", new_token.url_prefix) # token3 should not be allowed to change admin token token4 with self.assertRaises(Unauthorized) as ex: new_token = TokenFactory(token3).edit_token( token_gui=token4.token_gui, description="New description")
def test_dataset_element_removal(self): """ Factory can remove elements from datasets. """ anonymous = TokenDAO("Anonymous", 1, 1, "anonymous") destructor = TokenDAO("normal user privileged with link", 1, 1, "user1", privileges=Privileges.DESTROY_DATASET + Privileges.DESTROY_ELEMENTS ) destructor2 = TokenDAO("normal user unprivileged", 1, 1, "user1", privileges=Privileges.DESTROY_DATASET ) admin = TokenDAO("admin user", 1, 1, "admin", privileges=Privileges.ADMIN_CREATE_TOKEN + Privileges.ADMIN_EDIT_TOKEN + Privileges.ADMIN_DESTROY_TOKEN) dataset = DatasetDAO("user1/dataset1", "example_dataset", "dataset for testing purposes", "none", tags=["example", "0"]) dataset2 = DatasetDAO("user1/dataset2", "example_dataset2", "dataset2 for testing purposes", "none", tags=["example", "1"]) self.session.flush() destructor = destructor.link_dataset(dataset) destructor2 = destructor2.link_dataset(dataset2) file_id1 = storage.put_file_content(b"content1") file_id2 = storage.put_file_content(b"content2") element = DatasetElementDAO("example1", "none", file_id1, dataset=dataset) element2 = DatasetElementDAO("example2", "none", file_id1, dataset=dataset) element3 = DatasetElementDAO("example3", "none", file_id2, dataset=dataset2) self.session.flush() dataset = dataset.update() dataset2 = dataset2.update() self.assertEqual(len(dataset.elements), 2) self.assertEqual(len(dataset2.elements), 1) # Destructor can not destroy elements from a dataset that is not linked to with self.assertRaises(Unauthorized) as ex: DatasetElementFactory(destructor, dataset2).destroy_element(element._id) with self.assertRaises(Unauthorized) as ex: DatasetElementFactory(destructor, dataset2).destroy_element(element2._id) with self.assertRaises(Unauthorized) as ex: DatasetElementFactory(destructor, dataset2).destroy_element(element3._id) # Destructor can not destroy elements if they exist but are not inside his dataset with self.assertRaises(Unauthorized) as ex: DatasetElementFactory(destructor, dataset).destroy_element(element3._id) # Destructor can not destroy elements if they don't exist with self.assertRaises(Unauthorized) as ex: DatasetElementFactory(destructor, dataset).destroy_element("randomID") # Destructor can destroy elements if they exist and are inside his dataset DatasetElementFactory(destructor, dataset).destroy_element(element._id) # Even though element is destroyed, file referenced should still exist self.assertEqual(storage.get_file(file_id1).content, b"content1") dataset = dataset.update() self.assertEqual(len(dataset.elements), 1) # Admin can remove elements form any source DatasetElementFactory(admin, dataset).destroy_element(element2._id) DatasetElementFactory(admin, dataset2).destroy_element(element3._id) self.session.flush() dataset = dataset.update() dataset2 = dataset2.update() self.assertEqual(len(dataset.elements), 0) self.assertEqual(len(dataset2.elements), 0)
def test_dataset_fork_element_modification(self): """ Elements modified from a forked dataset do not affect the main dataset. :return: """ editor = TokenDAO("normal user privileged with link", 100, 200, "user1", privileges=Privileges.RO_WATCH_DATASET + Privileges.CREATE_DATASET + Privileges.EDIT_DATASET + Privileges.ADD_ELEMENTS + Privileges.EDIT_ELEMENTS + Privileges.DESTROY_ELEMENTS ) main_dataset = DatasetFactory(editor).create_dataset(url_prefix="foobar", title="foo", description="bar", reference="none", tags=["a"]) editor = editor.link_dataset(main_dataset) elements_proto = [{ 'title': 't{}'.format(i), 'description': 'desc{}'.format(i), 'http_ref': 'none', 'tags': ['none'], 'content': "content{}".format(i).encode() } for i in range(4)] elements = [DatasetElementFactory(editor, main_dataset).create_element(**element_proto) for element_proto in elements_proto] self.session.flush() self.assertEqual(len(elements), len(main_dataset.elements)) forked_dataset = DatasetFactory(editor).fork_dataset(main_dataset.url_prefix, editor, url_prefix="foo") editor.link_dataset(forked_dataset) self.session.flush() self.assertEqual(len(forked_dataset.elements), len(main_dataset.elements)) DatasetElementFactory(editor, forked_dataset).destroy_element(forked_dataset.elements[0]._id) self.session.flush() self.assertEqual(len(forked_dataset.elements), len(main_dataset.elements)-1) self.assertEqual(forked_dataset.elements[0].title, "t1") DatasetElementFactory(editor, main_dataset).destroy_element(main_dataset.elements[1]._id) self.session.flush() self.assertEqual(len(forked_dataset.elements), len(main_dataset.elements)) self.assertEqual(forked_dataset.elements[0].title, "t1") self.assertEqual(forked_dataset.elements[1].title, "t2") self.assertEqual(forked_dataset.elements[2].title, "t3") self.assertEqual(main_dataset.elements[0].title, "t0") self.assertEqual(main_dataset.elements[1].title, "t2") self.assertEqual(main_dataset.elements[2].title, "t3") DatasetElementFactory(editor, forked_dataset).edit_element(main_dataset.elements[2]._id, title='tc2') self.session.flush() self.assertEqual(main_dataset.elements[2].title, "t3") self.assertEqual(forked_dataset.elements[2].title, "tc2") DatasetElementFactory(editor, main_dataset).edit_element(main_dataset.elements[1]._id, title='tc') self.session.flush() self.assertEqual(main_dataset.elements[1].title, "tc") self.assertEqual(forked_dataset.elements[1].title, "t2") main_dataset = DatasetFactory(editor).create_dataset(url_prefix="foobar2", title="foo", description="bar", reference="none", tags=["a"]) editor.link_dataset(main_dataset) self.session.flush() elements_proto = [{ 'title': 't{}'.format(i), 'description': 'desc{}'.format(i), 'http_ref': 'none', 'tags': ['none'], 'content': "content{}".format(i).encode() } for i in range(4)] elements = [DatasetElementFactory(editor, main_dataset).create_element(**element_proto) for element_proto in elements_proto] self.session.flush() forked_dataset2 = DatasetFactory(editor).fork_dataset(main_dataset.url_prefix, editor, url_prefix="bar") self.session.flush() editor.link_dataset(forked_dataset2) self.session.flush() mod_proto = { main_dataset.elements[0]._id: dict(title="t3"), main_dataset.elements[1]._id: dict(title="t3_2"), } self.assertEqual(forked_dataset2.elements[0]._id, main_dataset.elements[0]._id) self.assertEqual(forked_dataset2.elements[1]._id, main_dataset.elements[1]._id) self.assertEqual(forked_dataset2.elements[2]._id, main_dataset.elements[2]._id) self.assertEqual(forked_dataset2.elements[3]._id, main_dataset.elements[3]._id) DatasetElementFactory(editor, main_dataset).edit_elements(mod_proto) self.session.flush() self.assertEqual(forked_dataset2.elements[0].title, "t0") self.assertEqual(forked_dataset2.elements[1].title, "t1") self.assertEqual(forked_dataset2.elements[2].title, "t2") self.assertEqual(forked_dataset2.elements[3].title, "t3") self.assertEqual(main_dataset.elements[0].title, "t3") self.assertEqual(main_dataset.elements[1].title, "t3_2") self.assertEqual(main_dataset.elements[2].title, "t2") self.assertEqual(main_dataset.elements[3].title, "t3") self.assertNotEqual(forked_dataset2.elements[0]._id, main_dataset.elements[0]._id) self.assertNotEqual(forked_dataset2.elements[1]._id, main_dataset.elements[1]._id) self.assertEqual(forked_dataset2.elements[2]._id, main_dataset.elements[2]._id) self.assertEqual(forked_dataset2.elements[3]._id, main_dataset.elements[3]._id) mod_proto = { forked_dataset2.elements[2]._id: dict(title="t4"), forked_dataset2.elements[3]._id: dict(title="t4_2"), } DatasetElementFactory(editor, forked_dataset2).edit_elements(mod_proto) self.assertNotEqual(forked_dataset2.elements[0]._id, main_dataset.elements[0]._id) self.assertNotEqual(forked_dataset2.elements[1]._id, main_dataset.elements[1]._id) self.assertNotEqual(forked_dataset2.elements[2]._id, main_dataset.elements[2]._id) self.assertNotEqual(forked_dataset2.elements[3]._id, main_dataset.elements[3]._id) self.assertEqual(forked_dataset2.elements[2].title, "t4") self.assertEqual(forked_dataset2.elements[3].title, "t4_2") self.assertEqual(main_dataset.elements[2].title, "t2") self.assertEqual(main_dataset.elements[3].title, "t3")
def test_dataset_element_edit(self): """ Factory can edit elements from datasets. """ editor = TokenDAO("normal user privileged with link", 1, 1, "user1", privileges=Privileges.EDIT_DATASET + Privileges.EDIT_ELEMENTS ) editor2 = TokenDAO("normal user unprivileged", 1, 1, "user1", privileges=Privileges.EDIT_DATASET ) admin = TokenDAO("admin user", 1, 1, "admin", privileges=Privileges.ADMIN_CREATE_TOKEN + Privileges.ADMIN_EDIT_TOKEN + Privileges.ADMIN_DESTROY_TOKEN) dataset = DatasetDAO("user1/dataset1", "example_dataset", "dataset for testing purposes", "none", tags=["example", "0"]) dataset2 = DatasetDAO("user1/dataset2", "example_dataset2", "dataset2 for testing purposes", "none", tags=["example", "1"]) self.session.flush() editor = editor.link_dataset(dataset) editor2 = editor2.link_dataset(dataset2) file_id1 = storage.put_file_content(b"content1") file_id2 = storage.put_file_content(b"content2") element = DatasetElementDAO("example1", "none", file_id1, dataset=dataset) element2 = DatasetElementDAO("example2", "none", file_id1, dataset=dataset) element3 = DatasetElementDAO("example3", "none", file_id2, dataset=dataset2) self.session.flush() dataset = dataset.update() dataset2 = dataset2.update() self.assertEqual(len(dataset.elements), 2) self.assertEqual(len(dataset2.elements), 1) # editor can not edit elements from a dataset that is not linked to with self.assertRaises(Unauthorized) as ex: DatasetElementFactory(editor, dataset2).edit_element(element._id, title="asd") with self.assertRaises(Unauthorized) as ex: DatasetElementFactory(editor, dataset2).edit_element(element2._id, title="asd2") with self.assertRaises(Unauthorized) as ex: DatasetElementFactory(editor, dataset2).edit_element(element3._id, title="asd3") # editor can not edit elements if they exist but are not inside his dataset with self.assertRaises(Unauthorized) as ex: DatasetElementFactory(editor, dataset).edit_element(element3._id, title="asd4") # editor can not edit elements if they don't exist with self.assertRaises(NotFound) as ex: DatasetElementFactory(editor, dataset).edit_element("randomID", title="asd5") # Editor can edit elements if they exist and are inside his dataset DatasetElementFactory(editor, dataset).edit_element(element._id, title="asd6") self.session.flush() dataset = dataset.update() element = element.update() # Editor can not change references to files with self.assertRaises(Unauthorized) as ex: DatasetElementFactory(editor, dataset).edit_element(element._id, file_ref_id="other_reference") # BUT he can change the content DatasetElementFactory(editor, dataset).edit_element(element._id, content=b"other_content") element = element.update() self.assertEqual(storage.get_file(element.file_ref_id).content, b"other_content") # Admin can do whatever he wants DatasetElementFactory(admin, dataset).edit_element(element2._id, title="changed by admin") element2 = element2.update() self.assertEqual(element2.title, "changed by admin") DatasetElementFactory(admin, dataset2).edit_element(element3._id, file_ref_id=element.file_ref_id) element3 = element3.update() self.assertEqual(storage.get_file(element3.file_ref_id).content, storage.get_file(element.file_ref_id).content) self.session.flush()
def test_dataset_element_creation(self): """ Factory can create dataset's elements. """ anonymous = TokenDAO("Anonymous", 1, 1, "anonymous") creator = TokenDAO("normal user privileged with link", 1, 1, "user1", privileges=Privileges.CREATE_DATASET + Privileges.ADD_ELEMENTS ) creator2 = TokenDAO("normal user unprivileged", 1, 1, "user1", privileges=Privileges.CREATE_DATASET ) admin = TokenDAO("admin user", 1, 1, "admin", privileges=Privileges.ADMIN_CREATE_TOKEN + Privileges.ADMIN_EDIT_TOKEN + Privileges.ADMIN_DESTROY_TOKEN) dataset = DatasetDAO("user1/dataset1", "example_dataset", "dataset for testing purposes", "none", tags=["example", "0"]) dataset2 = DatasetDAO("user1/dataset2", "example_dataset2", "dataset2 for testing purposes", "none", tags=["example", "1"]) self.session.flush() creator = creator.link_dataset(dataset) creator2 = creator2.link_dataset(dataset) # Creator can create elements into the dataset element = DatasetElementFactory(creator, dataset).create_element(title="New element", description="Description unknown", tags=["example_tag"], content=b"hello") self.assertEqual(element.tags, ["example_tag"]) content = storage.get_file(element.file_ref_id).content self.assertEqual(content, b"hello") self.session.flush() # Creator can't create elements referencing existing files directly (Exploit fix) with self.assertRaises(Unauthorized) as ex: element = DatasetElementFactory(creator, dataset).create_element(title="New element2", description="Description unknown2", tags=["example_tag"], file_ref_id=element.file_ref_id) # Creator can't create elements on other's datasets if not linked with them with self.assertRaises(Unauthorized) as ex: element = DatasetElementFactory(creator, dataset2).create_element(title="New element2", description="Description unknown2", tags=["example_tag"], content=b"hello2") # Anonymous can't create elements with self.assertRaises(Unauthorized) as ex: element = DatasetElementFactory(anonymous, dataset).create_element(title="New element3", description="Description unknown", tags=["example_tag"], content=b"hello3") # Creator2, even linked to the dataset, can't create elements as it is not privileged with self.assertRaises(Unauthorized) as ex: element = DatasetElementFactory(creator2, dataset).create_element(title="New element4", description="Description unknown4", tags=["example_tag"], content=b"hello4") # Admin can do any of the previous actions. element = DatasetElementFactory(admin, dataset).create_element(title="New element5", description="Description unknown5", tags=["example_tag"], content=b"hello5") self.session.flush_all() self.session.refresh(dataset) dataset = DatasetDAO.query.get(_id=dataset._id) self.assertIn(dataset._id, element.dataset_id) self.assertEqual(len(dataset.elements), 2) new_element = DatasetElementFactory(admin, dataset2).create_element(title="New element6", description="Description unknown5", tags=["example_tag"], file_ref_id=element.file_ref_id) self.assertEqual(element.file_ref_id, new_element.file_ref_id)
def test_dataset_element_content_retrieval(self): """ Factory can retrieve content of an element. """ editor = TokenDAO("normal user privileged with link", 1, 1, "user1", privileges=Privileges.RO_WATCH_DATASET ) editor2 = TokenDAO("normal user unprivileged", 1, 1, "user1", privileges=0 ) admin = TokenDAO("admin user", 1, 1, "admin", privileges=Privileges.ADMIN_CREATE_TOKEN + Privileges.ADMIN_EDIT_TOKEN + Privileges.ADMIN_DESTROY_TOKEN) dataset = DatasetDAO("user1/dataset1", "example_dataset", "dataset for testing purposes", "none", tags=["example", "0"]) dataset2 = DatasetDAO("user1/dataset2", "example_dataset2", "dataset2 for testing purposes", "none", tags=["example", "1"]) self.session.flush() editor = editor.link_dataset(dataset) editor2 = editor2.link_dataset(dataset2) file_id1 = storage.put_file_content(b"content1") file_id2 = storage.put_file_content(b"content2") element = DatasetElementDAO("example1", "none", file_id1, dataset=dataset) element2 = DatasetElementDAO("example2", "none", file_id1, dataset=dataset) element3 = DatasetElementDAO("example3", "none", file_id2, dataset=dataset2) self.session.flush() dataset = dataset.update() dataset2 = dataset2.update() self.assertEqual(len(dataset.elements), 2) self.assertEqual(len(dataset2.elements), 1) # editor can see elements from his dataset element_content = DatasetElementFactory(editor, dataset).get_element_content(element._id) self.assertEqual(element_content, b"content1") # editor can not see elements from other's datasets with self.assertRaises(Unauthorized) as ex: element_content = DatasetElementFactory(editor, dataset2).get_element_content(element3._id) # editor can not see external elements within his dataset with self.assertRaises(Unauthorized) as ex: element_content = DatasetElementFactory(editor, dataset).get_element_content(element3._id) # editor2 is not privileged and can not see any elements of his own dataset with self.assertRaises(Unauthorized) as ex: element_content = DatasetElementFactory(editor2, dataset2).get_element_content(element3._id) # Or external elements with self.assertRaises(Unauthorized) as ex: element_content = DatasetElementFactory(editor2, dataset2).get_element_content(element2._id) # Or other datasets with self.assertRaises(Unauthorized) as ex: element_content = DatasetElementFactory(editor2, dataset).get_element_content(element2._id) # Admin can do anything element_content = DatasetElementFactory(admin, dataset).get_element_content(element._id) self.assertEqual(element_content, b"content1") # But not this: dataset2 does not have element with self.assertRaises(Unauthorized) as ex: element_content = DatasetElementFactory(admin, dataset2).get_element_content(element._id) element_content = DatasetElementFactory(admin, dataset2).get_element_content(element3._id) self.assertEqual(element_content, b"content2")