def test_annotation_can_get_nestedpid_target_ids(self): example = copy.copy(examples["vincent-nestedpid"]) example_selector = example["target"][0]["selector"]["value"] annotation = Annotation(example) target_ids = annotation.get_target_ids() for resource in example_selector: self.assertTrue(resource["id"] in target_ids)
def test_annotation_can_get_nestedpid_targets_info(self): example = copy.copy(examples["vincent-nestedpid"]) example_selector = example["target"][0]["selector"]["value"] annotation = Annotation(example) targets_info = annotation.get_targets_info() for index, resource in enumerate(example_selector): self.assertTrue(resource["id"] in targets_info[index]["id"])
def test_annotation_can_get_subresource_target_ids(self): example = copy.copy(examples["vincent-subresource"]) example_selector = example["target"][0]["selector"]["value"] annotation = Annotation(example) target_ids = annotation.get_target_ids() self.assertTrue(example["target"][0]["source"] in target_ids) self.assertTrue(example_selector["subresource"]["id"] in target_ids)
def setUp(self): self.collection = AnnotationCollection( copy.copy(example_collections["empty_collection"])) self.annotations = [ Annotation(copy.copy(examples["vincent"])), Annotation(copy.copy(examples["theo"])) ] self.label = "Some collection" self.base_url = "http://localhost:3000/api/annotations"
def test_annotation_collection_can_remove_valid_annotation(self): collection = AnnotationCollection(self.collection) annotation = Annotation(copy.copy(examples["vincent"])) collection.add_annotation(annotation.id) self.assertEqual(collection.has_annotation(annotation.id), True) collection.remove_annotation(annotation.id) self.assertEqual(collection.has_annotation(annotation.id), False)
def add_annotation_es(self, annotation, params): # check if annotation is valid, add id and timestamp anno = Annotation(annotation) # if annotation already has ID, check if it already exists in the index if "id" in annotation: self.should_not_exist(annotation['id'], annotation['type']) # add permissions for access (see) and update (edit) permissions.add_permissions(anno, params) # create target_list for easy target-based retrieval self.add_target_list(anno) # index annotation self.add_to_index(anno.to_json(), annotation["type"]) # set index needs refresh before next GET self.set_index_needs_refresh() # exclude target_list and permissions when returning annotation return anno.to_clean_json(params)
def test_other_user_can_see_public_annotation(self): annotation = Annotation(self.example_annotation) permissions.add_permissions(annotation, self.public_params) params = {"username": "******"} self.assertEqual( permissions.is_allowed_to_see(params["username"], annotation), True)
def get_target_list(self, annotation): target_list = annotation.get_targets_info() deeper_targets = [] for target in target_list: if self.is_annotation(target): if target["id"] == annotation.id: raise AnnotationError( message="Annotation cannot target itself") if self.is_deleted(target["id"]): continue target_annotation = self.get_annotation_es(target['id'], params={ "username": None, "action": "traverse" }) deeper_targets += self.get_target_list( Annotation(target_annotation)) target_ids = [target["id"] for target in target_list] for target in deeper_targets: if target not in target_ids: target_list += [target] target_ids += [target["id"]] return target_list
def test_other_user_cannot_edit_private_annotation(self): annotation = Annotation(self.example_annotation) permissions.add_permissions(annotation, self.private_params) params = {"username": "******"} self.assertEqual( permissions.is_allowed_to_edit(params["username"], annotation), False)
def get_objects_from_hits(self, hits): objects = [] for hit in hits: if hit["_source"]["type"] == "Annotation": objects += [Annotation(hit["_source"])] elif hit["_source"]["type"] == "AnnotationCollection": objects += [AnnotationCollection(hit["_source"])]
def is_annotation_list(self, annotations): if not isinstance(annotations, list): return False for annotation in annotations: try: Annotation(copy.copy(annotation)) # copy to make sure annotation is not changed except AnnotationError: return False return True
def test_annotation_collection_can_generate_an_annotation_collection_json( self): collection = AnnotationCollection(self.collection) annotation = Annotation(copy.copy(examples["vincent"])) collection.add_annotation(annotation.id) collection_json = collection.to_json() self.assertEqual(collection_json["id"], collection.id) self.assertEqual(collection_json["total"], 1) self.assertEqual(collection_json["items"][0], annotation.id)
def test_other_user_who_can_edit_can_also_see_shared_annotation(self): annotation = Annotation(self.example_annotation) permissions.add_permissions(annotation, self.shared_params) params = {"username": "******"} self.assertEqual( permissions.is_allowed_to_edit(params["username"], annotation), True) self.assertEqual( permissions.is_allowed_to_see(params["username"], annotation), True)
def validate_and_commit_json(name, data): if isinstance(data, (list)): for d in data: if not validate(d): return False for d in data: annotation = Annotation(collection=name, data=d) db.session.add(annotation) db.session.commit() return True elif isinstance(data, (dict)): if not validate(data): return False annotation = Annotation(collection=name, data=data) db.session.add(annotation) db.session.commit() return True else: return False
def test_container_generate_page_referencing(self): annotations = [ Annotation(copy.copy(examples["vincent"])), Annotation(copy.copy(examples["theo"])), Annotation(copy.copy(examples["brothers"])) ] container = AnnotationContainer(self.base_url, annotations, page_size=1) view0 = container.view_page(page=0) view1 = container.view_page(page=1) view2 = container.view_page(page=2) self.assertEqual(view0["next"], view1["id"]) self.assertEqual(view0["next"], view2["prev"]) self.assertEqual(view1["prev"], view0["id"]) self.assertEqual(view1["next"], view2["id"]) self.assertEqual(view2["prev"], view1["id"]) items = view0["items"] + view1["items"] + view2["items"] for anno in annotations: self.assertTrue(anno.id in items)
def collection(name): if not Collection.exists(name): return jsonify({'status': 'Resource does not exist.'}), 405 if request.method == 'GET': return annotations_for(name), 200 elif request.method == 'PUT': if not request.is_json: return jsonify({'status': 'Expected JSON.'}), 400 data = request.get_json() annotation = Annotation(collection=name, data=data) if not validate_and_commit_json(name, data): return jsonify({'status': 'Poorly formatted JSON.'}), 400 return jsonify({'status': 'Annotation data added.'}), 202
def get_annotations_es(self, params): # check index is up to date, refresh if needed self.check_index_is_fresh() response = self.get_from_index_by_filters(params, annotation_type="Annotation") annotations = [ Annotation(hit["_source"]) for hit in response["hits"]["hits"] ] return { "total": response["hits"]["total"], "annotations": [annotation.to_clean_json(params) for annotation in annotations] }
def test_can_see_user_cannot_edit_shared_annotation(self): annotation = Annotation(self.example_annotation) params = { "access_status": "shared", "username": "******", "can_see": ["user2", "user3"], "can_edit": ["user4"] } permissions.add_permissions(annotation, params) self.assertEqual( permissions.is_allowed_action(params["can_see"][0], "see", annotation), True) self.assertEqual( permissions.is_allowed_action(params["can_see"][0], "edit", annotation), False)
def update_chained_annotations(self, annotation_id): # first refresh the index self.es.indices.refresh(index=self.es_index) chain_annotations = self.get_from_index_by_target( {"id": annotation_id}) for chain_annotation in chain_annotations: if chain_annotation["id"] == annotation_id: raise AnnotationError( message="Annotation cannot target itself") chain_annotation["target_list"] = self.get_target_list( Annotation(chain_annotation)) # don't use permission parameters for chained annotations self.update_annotation_es(chain_annotation, params={ "username": None, "action": "traverse" })
def get_from_index_if_allowed(self, annotation_id, username, action, annotation_type="_all"): # check index is up to date, refresh if needed self.check_index_is_fresh() # check that annotation exists (and is not deleted) self.should_exist(annotation_id, annotation_type) # get original annotation json annotation_json = self.get_from_index_by_id(annotation_id, annotation_type) annotation = Annotation(annotation_json) if annotation_json[ "type"] == "Annotation" else AnnotationCollection(annotation_json) # check if user has appropriate permissions if not permissions.is_allowed_action(username, action, annotation): raise PermissionError( message="Unauthorized access - no permission to {a} annotation" .format(a=action)) return annotation
def remove_from_index_if_allowed(self, annotation_id, params, annotation_type="_all"): if "username" not in params: params["username"] = None # check index is up to date, refresh if needed self.check_index_is_fresh() # check that annotation exists (and is not deleted) self.should_exist(annotation_id, annotation_type) # get original annotation json annotation_json = self.get_from_index_by_id(annotation_id, annotation_type) # check if user has appropriate permissions if not permissions.is_allowed_action(params["username"], "edit", Annotation(annotation_json)): raise PermissionError( message="Unauthorized access - no permission to {a} annotation" .format(a=params["action"])) return self.remove_from_index(annotation_id, "Annotation")
def setUp(self): self.annotation = Annotation(copy.copy(examples["vincent"]))
def test_anonymous_user_can_see_public_annotation(self): annotation = Annotation(self.example_annotation) permissions.add_permissions(annotation, self.public_params) self.assertEqual( permissions.is_allowed_to_see(self.anon_params["username"], annotation), True)
def test_owner_user_can_see_shared_annotation(self): annotation = Annotation(self.example_annotation) permissions.add_permissions(annotation, self.shared_params) self.assertEqual( permissions.is_allowed_to_see(self.private_params["username"], annotation), True)
def test_annotation_collection_can_retrieve_annotation(self): collection = AnnotationCollection(self.collection) annotation = Annotation(copy.copy(examples["vincent"])) collection.add_annotation(annotation.id) self.assertTrue(collection.has_annotation(annotation.id))
class TestAnnotation(unittest.TestCase): def setUp(self): self.annotation = Annotation(copy.copy(examples["vincent"])) def test_annotation_has_id(self): self.assertTrue('id' in self.annotation.data) self.assertEqual(self.annotation.id, self.annotation.data['id']) def test_annotation_has_creation_timestamp(self): self.assertTrue('created' in self.annotation.data) def test_annotation_can_update(self): update_annotation = self.annotation.data new_motivation = "linking" update_annotation['motivation'] = new_motivation self.annotation.update(update_annotation) # annotation must have 'linking' motivation self.assertEqual(self.annotation.data['motivation'], new_motivation) # annotation must have a 'modified' timestamp self.assertTrue('modified' in self.annotation.data) def test_annotation_can_get_target_ids(self): target_ids = self.annotation.get_target_ids() example_target = examples["vincent"]["target"][0] self.assertTrue(example_target["id"] in target_ids) def test_annotation_can_get_subresource_target_ids(self): example = copy.copy(examples["vincent-subresource"]) example_selector = example["target"][0]["selector"]["value"] annotation = Annotation(example) target_ids = annotation.get_target_ids() self.assertTrue(example["target"][0]["source"] in target_ids) self.assertTrue(example_selector["subresource"]["id"] in target_ids) def test_annotation_can_get_nestedpid_target_ids(self): example = copy.copy(examples["vincent-nestedpid"]) example_selector = example["target"][0]["selector"]["value"] annotation = Annotation(example) target_ids = annotation.get_target_ids() for resource in example_selector: self.assertTrue(resource["id"] in target_ids) def test_annotation_can_get_targets_info(self): targets_info = self.annotation.get_targets_info() example_target = examples["vincent"]["target"][0] self.assertTrue(example_target["id"] in targets_info[0]["id"]) def test_annotation_can_get_subresource_targets_info(self): example = copy.copy(examples["vincent-subresource"]) example_selector = example["target"][0]["selector"]["value"] annotation = Annotation(example) targets_info = annotation.get_targets_info() self.assertTrue( example["target"][0]["source"] in targets_info[0]["id"]) self.assertTrue( example_selector["subresource"]["id"] in targets_info[1]["id"]) def test_annotation_can_get_nestedpid_targets_info(self): example = copy.copy(examples["vincent-nestedpid"]) example_selector = example["target"][0]["selector"]["value"] annotation = Annotation(example) targets_info = annotation.get_targets_info() for index, resource in enumerate(example_selector): self.assertTrue(resource["id"] in targets_info[index]["id"])
def annotations(): grafana_annotation = json.loads(request.data.decode("utf-8")) annotation = Annotation(grafana_annotation) responder = Responder(Responder.get_data_store()) return json.dumps(responder.annotation(annotation)), 200
def test_anonymous_user_cannot_edit_shared_annotation(self): annotation = Annotation(self.example_annotation) permissions.add_permissions(annotation, self.shared_params) self.assertEqual( permissions.is_allowed_to_edit(self.anon_params["username"], annotation), False)
def test_annotation_collection_can_add_valid_annotation(self): collection = AnnotationCollection(self.collection) annotation = Annotation(copy.copy(examples["vincent"])) collection.add_annotation(annotation.id) self.assertEqual(collection.size(), 1)