class TestBackgroundTask(TestCase): """Tests for background task model.""" def setUp(self): """setUp, nothing else to add.""" super(TestBackgroundTask, self).setUp() self.object_generator = ObjectGenerator() self.api = api_helper.Api() def test_bg_task_from_post(self): """Test filtering of GET response for BackgroundTask""" from ggrc.models import all_models response, _ = self.object_generator.generate_object( all_models.Control, with_background_tasks=True) self.assertEqual(response.status_code, 201) bg_tasks = all_models.BackgroundTask.query.filter( all_models.BackgroundTask.name.like("%POST%")).all() self.assertEqual(len(bg_tasks), 1) content = self.api.client.get("/api/background_tasks") self.assert200(content) bg_tasks_content = \ content.json['background_tasks_collection']['background_tasks'] self.assertEqual(set(bg_tasks_content[0].keys()), {"id", "selfLink", "status", "type"}) task_id = bg_tasks[0].id content = self.api.client.get( "/api/background_tasks/{}".format(task_id)) self.assert200(content) bg_task_content = \ content.json['background_task'] self.assertEqual(set(bg_task_content.keys()), {"id", "selfLink", "status", "type"})
class TestBackgroundTask(TestCase): """Tests for background task model.""" def setUp(self): """setUp, nothing else to add.""" super(TestBackgroundTask, self).setUp() self.api = api_helper.Api() self.object_generator = ObjectGenerator() def test_bg_task_from_post(self): """Test filtering of GET response for BackgroundTask""" from ggrc.models import all_models with self.object_generator.api.as_external(): response, _ = self.object_generator.generate_object( all_models.Control, with_background_tasks=True) self.assertEqual(response.status_code, 201) bg_tasks = all_models.BackgroundTask.query.filter( all_models.BackgroundTask.name.like("%POST%")).all() self.assertEqual(len(bg_tasks), 1) content = self.api.client.get("/api/background_tasks") self.assert200(content) bg_tasks_content = \ content.json['background_tasks_collection']['background_tasks'] self.assertEqual(set(bg_tasks_content[0].keys()), {"id", "selfLink", "status", "type"}) task_id = bg_tasks[0].id content = self.api.client.get("/api/background_tasks/{}".format(task_id)) self.assert200(content) bg_task_content = \ content.json['background_task'] self.assertEqual(set(bg_task_content.keys()), {"id", "selfLink", "status", "type"})
class TestResource(TestCase): """ Test /search REST API """ def setUp(self): super(TestResource, self).setUp() self.api = Api() self.object_generator = ObjectGenerator() self.create_objects() def create_objects(self): """Create objects to be searched. Creates five Requirements and makes relationships. 0 1 2 3 4 |---| |---| | |-------|-------| """ self.objects = [ self.object_generator.generate_object(all_models.Requirement)[1].id for _ in xrange(5) ] self.objects = all_models.Requirement.eager_query().filter( all_models.Requirement.id.in_(self.objects) ).all() for src, dst in [(0, 1), (0, 2), (2, 3), (2, 4)]: self.object_generator.generate_relationship( self.objects[src], self.objects[dst] ) def search(self, *args, **kwargs): res, _ = self.api.search(*args, **kwargs) return res.json["results"]["entries"] def test_search_all(self): """Test search for all objects of a type.""" res, _ = self.api.search("Requirement") self.assertEqual(len(res.json["results"]["entries"]), 5) def test_search_query(self): """Test search with query by title.""" entries = self.search("Requirement", query=self.objects[0].title) self.assertEqual({entry["id"] for entry in entries}, {self.objects[0].id}) def test_search_relevant(self): """Test search with 'relevant to' single object.""" relevant_objects = "Requirement:{}".format(self.objects[0].id) entries = self.search("Requirement", relevant_objects=relevant_objects) self.assertEqual({entry["id"] for entry in entries}, {self.objects[i].id for i in [1, 2]}) def test_search_relevant_multi(self): """Test search with 'relevant to' multiple objects.""" ids = ",".join("Requirement:{}".format(self.objects[i].id) for i in (0, 3)) entries = self.search("Requirement", relevant_objects=ids) self.assertEqual({entry["id"] for entry in entries}, {self.objects[2].id})
class TestResource(TestCase): """ Test /search REST API """ def setUp(self): super(TestResource, self).setUp() self.api = Api() self.object_generator = ObjectGenerator() self.create_objects() def create_objects(self): """Create objects to be searched. Creates five Requirements and makes relationships. 0 1 2 3 4 |---| |---| | |-------|-------| """ self.objects = [ self.object_generator.generate_object(all_models.Requirement)[1].id for _ in xrange(5) ] self.objects = all_models.Requirement.eager_query().filter( all_models.Requirement.id.in_(self.objects)).all() for src, dst in [(0, 1), (0, 2), (2, 3), (2, 4)]: self.object_generator.generate_relationship( self.objects[src], self.objects[dst]) def search(self, *args, **kwargs): res, _ = self.api.search(*args, **kwargs) return res.json["results"]["entries"] def test_search_all(self): """Test search for all objects of a type.""" res, _ = self.api.search("Requirement") self.assertEqual(len(res.json["results"]["entries"]), 5) def test_search_query(self): """Test search with query by title.""" entries = self.search("Requirement", query=self.objects[0].title) self.assertEqual({entry["id"] for entry in entries}, {self.objects[0].id}) def test_search_relevant(self): """Test search with 'relevant to' single object.""" relevant_objects = "Requirement:{}".format(self.objects[0].id) entries = self.search("Requirement", relevant_objects=relevant_objects) self.assertEqual({entry["id"] for entry in entries}, {self.objects[i].id for i in [1, 2]}) def test_search_relevant_multi(self): """Test search with 'relevant to' multiple objects.""" ids = ",".join("Requirement:{}".format(self.objects[i].id) for i in (0, 3)) entries = self.search("Requirement", relevant_objects=ids) self.assertEqual({entry["id"] for entry in entries}, {self.objects[2].id})
class TestRiskSnapshotting(TestCase): """Risk snapshot tests""" def setUp(self): """setUp, nothing else to add.""" super(TestRiskSnapshotting, self).setUp() self.api = api_helper.Api() self.api.login_as_external() self.objgen = ObjectGenerator() def test_update_risk_snapshot(self): """Update risk snapshot to the latest version""" with factories.single_commit(): program = factories.ProgramFactory(title="P1") risk = factories.RiskFactory(title="R1") risk_id = risk.id factories.RelationshipFactory(source=program, destination=risk) # Risk snapshot created for audit during mapping audit to program self.objgen.generate_object( all_models.Audit, { "title": "A1", "program": { "id": program.id }, "status": "Planned", "snapshots": { "operation": "create", } }) # Update risk to get outdated snapshot (new risk revision) risk = all_models.Risk.query.get(risk_id) self.api.put(risk, {"title": "New risk title"}) audit = all_models.Audit.query.filter_by(title="A1").one() snapshot = all_models.Snapshot.query.first() self.assertEquals(audit, snapshot.parent) # Update snapshot to the latest revision res = self.api.put(snapshot, {"update_revision": "latest"}) self.assert200(res) self.assertTrue(res.json["snapshot"]["is_latest_revision"])
class TestPermissions(TestCase): """Test permissions for background tasks""" def setUp(self): super(TestPermissions, self).setUp() self.api = api_helper.Api() self.object_generator = ObjectGenerator() self.init_users() def init_users(self): """ Init users needed by the test cases """ users = [("reader", "Reader"), ("admin", "Administrator"), ("creator", "Creator")] self.users = {} for (name, role) in users: _, user = self.object_generator.generate_person( data={"name": name}, user_role=role) self.users[name] = user def test_bg_tasks_access(self): """Only admin can use admin requirement""" from ggrc.models import all_models with self.object_generator.api.as_external(): response, _ = self.object_generator.generate_object( all_models.Control, with_background_tasks=True) self.assertEqual(response.status_code, 201) for role in ("reader", "creator", "admin"): self.api.set_user(self.users[role]) content = self.api.client.get("/api/background_tasks") self.assert200(content) bg_tasks_content = \ content.json['background_tasks_collection']['background_tasks'] for bg_task_content in bg_tasks_content: self.assertEqual(set(bg_task_content.keys()), {"id", "selfLink", "status", "type"}) self.assertTrue(len(bg_tasks_content) >= 1)
class TestPermissions(TestCase): """Test permissions for background tasks""" def setUp(self): super(TestPermissions, self).setUp() self.api = api_helper.Api() self.object_generator = ObjectGenerator() self.init_users() def init_users(self): """ Init users needed by the test cases """ users = [("reader", "Reader"), ("admin", "Administrator"), ("creator", "Creator")] self.users = {} for (name, role) in users: _, user = self.object_generator.generate_person( data={"name": name}, user_role=role) self.users[name] = user def test_bg_tasks_access(self): """Only admin can use admin requirement""" from ggrc.models import all_models response, _ = self.object_generator.generate_object( all_models.Control, with_background_tasks=True) self.assertEqual(response.status_code, 201) for role in ("reader", "creator", "admin"): self.api.set_user(self.users[role]) content = self.api.client.get("/api/background_tasks") self.assert200(content) bg_tasks_content = \ content.json['background_tasks_collection']['background_tasks'] for bg_task_content in bg_tasks_content: self.assertEqual(set(bg_task_content.keys()), {"id", "selfLink", "status", "type"}) self.assertTrue(len(bg_tasks_content) >= 1)
class TestWithExtCustomAttrsSetter(TestCase): """Test WithReadOnlyAccess mixin""" def setUp(self): super(TestWithExtCustomAttrsSetter, self).setUp() self.object_generator = ObjectGenerator() self.object_generator.api.login_as_normal() @staticmethod def _create_cads(obj_type, names=('ATTR1', 'ATTR2', 'ATTR3')): """Create custom attribute definitions""" ret = dict() with factories.single_commit(): for name in names: obj = factories.CustomAttributeDefinitionFactory( title=name, definition_type=obj_type.lower(), attribute_type="Text", ) ret[name] = obj.id return ret @staticmethod def _create_model(obj_type, cad_map, cavs): """Create model and assign CAVs""" with factories.single_commit(): obj = factories.get_model_factory(obj_type)() for name, value in cavs.iteritems(): cad = get_model('CustomAttributeDefinition').query.get(cad_map[name]) factories.CustomAttributeValueFactory( custom_attribute=cad, attributable=obj, attribute_value=value, ) return obj.id @staticmethod def _get_orig_cav_list(cad_map, name_to_val): """Return list of original cav in request json""" return list( { 'custom_attribute_id': cad_map[name], 'attribute_value': val, 'attribute_object': None, } for name, val in name_to_val.iteritems() ) @staticmethod def _get_external_cav_list(name_to_val): """Return list of external cav in request json""" return list( { 'name': name, 'value': val, } for name, val in name_to_val.iteritems() ) @ddt.data('System') def test_post_orig_cavs(self, obj_type): """Test POST orig cav for {0!r} for normal user""" cad_map = self._create_cads(obj_type) vals = dict((name, name) for name in cad_map) resp, obj = self.object_generator.generate_object( get_model(obj_type), data={ 'custom_attribute_values': self._get_orig_cav_list(cad_map, vals), } ) self.assertStatus(resp, 201) exp = dict((cad_map[name], name) for name in cad_map) cav = dict((i.custom_attribute_id, i.attribute_value) for i in obj.custom_attribute_values) self.assertDictEqual(cav, exp) @ddt.data('System') def test_post_orig_cavs_external(self, obj_type): """Test POST orig cav for {0!r} for external user""" cad_map = self._create_cads(obj_type) self.object_generator.api.login_as_external() vals = dict((name, name) for name in cad_map) resp, obj = self.object_generator.generate_object( get_model(obj_type), data={ 'custom_attribute_values': self._get_orig_cav_list(cad_map, vals), } ) self.assertStatus(resp, 201) exp = dict((cad_map[name], name) for name in cad_map) cav = dict((i.custom_attribute_id, i.attribute_value) for i in obj.custom_attribute_values) self.assertDictEqual(cav, exp) @ddt.data('System') def test_post_ext_cavs(self, obj_type): """Test POST external cav for {0!r} for normal user""" cad_map = self._create_cads(obj_type) vals = dict((name, name) for name in cad_map) resp, obj = self.object_generator.generate_object( get_model(obj_type), data={ 'external_custom_attributes': self._get_external_cav_list(vals), } ) self.assertStatus(resp, 201) exp = dict() cav = dict((i.custom_attribute_id, i.attribute_value) for i in obj.custom_attribute_values) self.assertDictEqual(cav, exp) @ddt.data('System') def test_post_ext_cavs_external(self, obj_type): """Test POST external cav for {0!r} for external user""" cad_map = self._create_cads(obj_type) self.object_generator.api.login_as_external() vals = dict((name, name) for name in cad_map) resp, obj = self.object_generator.generate_object( get_model(obj_type), data={ 'external_custom_attributes': self._get_external_cav_list(vals), } ) self.assertStatus(resp, 201) exp = dict((cad_map[name], name) for name in cad_map) cav = dict((i.custom_attribute_id, i.attribute_value) for i in obj.custom_attribute_values) self.assertDictEqual(cav, exp) @ddt.data('System') def test_post_ext_and_orig_cavs_external(self, obj_type): """Test POST external and orig cav for {0!r} are specified for ext user""" cad_map = self._create_cads(obj_type) self.object_generator.api.login_as_external() orig_vals = dict((name, '{}-1'.format(name)) for name in cad_map) ext_vals = dict((name, name) for name in cad_map) resp, obj = self.object_generator.generate_object( get_model(obj_type), data={ 'custom_attribute_values': self._get_orig_cav_list( cad_map, orig_vals), 'external_custom_attributes': self._get_external_cav_list( ext_vals), } ) self.assertStatus(resp, 201) exp = dict((cad_map[name], name) for name in cad_map) cav = dict((i.custom_attribute_id, i.attribute_value) for i in obj.custom_attribute_values) self.assertDictEqual(cav, exp) @ddt.data('System') def test_post_not_existing_cavs_external(self, obj_type): """Test POST missing cav for {0!r} are specified for external user""" cad_map = self._create_cads(obj_type) self.object_generator.api.login_as_external() vals = dict((name, name) for name in cad_map) vals['NEW'] = 'NEWVAL' resp, obj = self.object_generator.generate_object( get_model(obj_type), data={ 'external_custom_attributes': self._get_external_cav_list(vals), } ) self.assertStatus(resp, 201) exp = dict((cad_map[name], name) for name in cad_map) cav = dict((i.custom_attribute_id, i.attribute_value) for i in obj.custom_attribute_values) self.assertDictEqual(cav, exp) @ddt.data('System') def test_post_not_all_cavs_external(self, obj_type): """Test POST not all cavs for {0!r} are specified for external user""" cad_map = self._create_cads(obj_type) self.object_generator.api.login_as_external() vals = dict((name, name) for name in cad_map if name != "ATTR1") resp, obj = self.object_generator.generate_object( get_model(obj_type), data={ 'external_custom_attributes': self._get_external_cav_list(vals), } ) self.assertStatus(resp, 201) exp = dict((cad_map[name], name) for name in cad_map if name != "ATTR1") cav = dict((i.custom_attribute_id, i.attribute_value) for i in obj.custom_attribute_values) self.assertDictEqual(cav, exp) @ddt.data('System') def test_post_not_all_mandatory_cavs_external(self, obj_type): """Test POST not all cavs for {0!r} are specified for external user""" cad_map = self._create_cads(obj_type) factories.CustomAttributeDefinitionFactory( title="M-ATTR1", definition_type=obj_type.lower(), attribute_type="Text", mandatory=True ) self.object_generator.api.login_as_external() vals = dict((name, name) for name in cad_map) resp, obj = self.object_generator.generate_object( get_model(obj_type), data={ 'external_custom_attributes': self._get_external_cav_list(vals), } ) self.assertStatus(resp, 201) exp = dict((cad_map[name], name) for name in cad_map) cav = dict((i.custom_attribute_id, i.attribute_value) for i in obj.custom_attribute_values) self.assertDictEqual(cav, exp) @ddt.data('System') def test_put_orig_cavs(self, obj_type): """Test PUT orig cav for {0!r} for normal user""" cad_map = self._create_cads(obj_type) orig_cavs = dict( (name, '{}-orig'.format(name)) for name in cad_map ) obj_id = self._create_model(obj_type, cad_map, orig_cavs) vals = dict((name, name) for name in cad_map) obj = get_model(obj_type).query.get(obj_id) resp, obj = self.object_generator.modify( obj, obj_type.lower(), data={ 'custom_attribute_values': self._get_orig_cav_list(cad_map, vals), } ) self.assert200(resp) exp = dict((cad_map[name], name) for name in cad_map) cav = dict((i.custom_attribute_id, i.attribute_value) for i in obj.custom_attribute_values) self.assertDictEqual(cav, exp) @ddt.data('System') def test_put_orig_cavs_external(self, obj_type): """Test PUT orig cav for {0!r} for external user""" cad_map = self._create_cads(obj_type) orig_cavs = dict( (name, '{}-orig'.format(name)) for name in cad_map ) obj_id = self._create_model(obj_type, cad_map, orig_cavs) self.object_generator.api.login_as_external() vals = dict((name, name) for name in cad_map) obj = get_model(obj_type).query.get(obj_id) resp, obj = self.object_generator.modify( obj, obj_type.lower(), data={ 'custom_attribute_values': self._get_orig_cav_list(cad_map, vals), } ) self.assert200(resp) exp = dict((cad_map[name], name) for name in cad_map) cav = dict((i.custom_attribute_id, i.attribute_value) for i in obj.custom_attribute_values) self.assertDictEqual(cav, exp) @ddt.data('System') def test_put_ext_cavs(self, obj_type): """Test PUT external cav for {0!r} for normal user""" cad_map = self._create_cads(obj_type) orig_cavs = dict( (name, '{}-orig'.format(name)) for name in cad_map ) obj_id = self._create_model(obj_type, cad_map, orig_cavs) vals = dict((name, name) for name in cad_map) obj = get_model(obj_type).query.get(obj_id) resp, obj = self.object_generator.modify( obj, obj_type.lower(), data={ 'external_custom_attributes': self._get_external_cav_list(vals), } ) self.assert200(resp) exp = dict((cad_map[name], orig_cavs[name]) for name in cad_map) cav = dict((i.custom_attribute_id, i.attribute_value) for i in obj.custom_attribute_values) self.assertDictEqual(cav, exp) @ddt.data('System') def test_put_ext_cavs_external(self, obj_type): """Test PUT external cav for {0!r} for external user""" cad_map = self._create_cads(obj_type) orig_cavs = dict( (name, '{}-orig'.format(name)) for name in cad_map ) obj_id = self._create_model(obj_type, cad_map, orig_cavs) self.object_generator.api.login_as_external() vals = dict((name, name) for name in cad_map) obj = get_model(obj_type).query.get(obj_id) resp, obj = self.object_generator.modify( obj, obj_type.lower(), data={ 'external_custom_attributes': self._get_external_cav_list(vals), } ) self.assert200(resp) exp = dict((cad_map[name], name) for name in cad_map) cav = dict((i.custom_attribute_id, i.attribute_value) for i in obj.custom_attribute_values) self.assertDictEqual(cav, exp) @ddt.data('System') def test_put_ext_and_orig_cavs_external(self, obj_type): """Test PUT external and orig cav for {0!r} are specified for ext user""" cad_map = self._create_cads(obj_type) orig_cavs = dict( (name, '{}-orig'.format(name)) for name in cad_map ) obj_id = self._create_model(obj_type, cad_map, orig_cavs) self.object_generator.api.login_as_external() orig_vals = dict((name, '{}-1'.format(name)) for name in cad_map) ext_vals = dict((name, name) for name in cad_map) obj = get_model(obj_type).query.get(obj_id) resp, obj = self.object_generator.modify( obj, obj_type.lower(), data={ 'custom_attribute_values': self._get_orig_cav_list( cad_map, orig_vals), 'external_custom_attributes': self._get_external_cav_list( ext_vals), } ) self.assert200(resp) exp = dict((cad_map[name], name) for name in cad_map) cav = dict((i.custom_attribute_id, i.attribute_value) for i in obj.custom_attribute_values) self.assertDictEqual(cav, exp) @ddt.data('System') def test_put_not_existing_cavs_external(self, obj_type): """Test PUT missing cav for {0!r} are specified for external user""" cad_map = self._create_cads(obj_type) orig_cavs = dict( (name, '{}-orig'.format(name)) for name in cad_map ) obj_id = self._create_model(obj_type, cad_map, orig_cavs) self.object_generator.api.login_as_external() vals = dict((name, name) for name in cad_map) vals['NEW'] = 'NEWVAL' obj = get_model(obj_type).query.get(obj_id) resp, obj = self.object_generator.modify( obj, obj_type.lower(), data={ 'external_custom_attributes': self._get_external_cav_list(vals), } ) self.assert200(resp) exp = dict((cad_map[name], name) for name in cad_map) cav = dict((i.custom_attribute_id, i.attribute_value) for i in obj.custom_attribute_values) self.assertDictEqual(cav, exp) @ddt.data('System') def test_put_not_all_cavs_external(self, obj_type): """Test PUT not all cavs for {0!r} are specified for external user""" cad_map = self._create_cads(obj_type) orig_cavs = dict( (name, '{}-orig'.format(name)) for name in cad_map ) obj_id = self._create_model(obj_type, cad_map, orig_cavs) self.object_generator.api.login_as_external() vals = dict((name, name) for name in cad_map if name != 'ATTR1') obj = get_model(obj_type).query.get(obj_id) resp, obj = self.object_generator.modify( obj, obj_type.lower(), data={ 'external_custom_attributes': self._get_external_cav_list(vals), } ) self.assert200(resp) exp = dict((cad_map[name], name if name != 'ATTR1' else orig_cavs['ATTR1']) for name in cad_map) cav = dict((i.custom_attribute_id, i.attribute_value) for i in obj.custom_attribute_values) self.assertDictEqual(cav, exp)
class TestReader(TestCase): """ Test reader role """ def setUp(self): super(TestReader, self).setUp() self.api = Api() self.object_generator = ObjectGenerator() self.init_users() def init_users(self): """ Init users needed by the test cases """ users = [("reader", "Reader"), ("admin", "Administrator"), ("creator", "Creator")] self.users = {} for (name, role) in users: _, user = self.object_generator.generate_person( data={"name": name}, user_role=role) self.users[name] = user def test_admin_page_access(self): """Only admin can use admin requirement""" for role, code in (("reader", 403), ("admin", 200)): self.api.set_user(self.users[role]) self.assertEqual(self.api.client.get("/admin").status_code, code) def test_reader_can_crud(self): """ Test Basic create/read,update/delete operations """ self.api.set_user(self.users["reader"]) all_errors = [] base_models = set([ "Control", "DataAsset", "Contract", "Policy", "Regulation", "Standard", "Document", "Facility", "Market", "Objective", "OrgGroup", "Vendor", "Product", "System", "Process", "Project", "AccessGroup", "Metric", "TechnologyEnvironment", "ProductGroup", ]) for model_singular in base_models: try: model = get_model(model_singular) table_singular = model._inflector.table_singular table_plural = model._inflector.table_plural # Test POST creation response, _ = self.object_generator.generate_object( model, data={ table_singular: { "title": model_singular, "context": None, "documents_reference_url": "ref", "link": "https://example.com", # only for Document "contact": { "type": "Person", "id": self.users["reader"].id, } }, }) if response.status_code != 201: all_errors.append("{} post creation failed {} {}".format( model_singular, response.status, response.data)) continue obj_id = response.json.get(table_singular).get("id") # Test GET when owner response = self.api.get(model, obj_id) if response.status_code != 200: all_errors.append("{} can't GET object {}".format( model_singular, response.status)) continue # Test GET collection when owner response = self.api.get_collection(model, obj_id) collection = response.json.get( "{}_collection".format(table_plural)).get(table_plural) if not collection: all_errors.append( "{} cannot retrieve object even if owner (collection)". format(model_singular)) continue except: all_errors.append("{} exception thrown".format(model_singular)) raise self.assertEqual(all_errors, []) def test_reader_search(self): """ Test if reader can see the correct object while using search api """ self.api.set_user(self.users['admin']) self.api.post(all_models.Regulation, { "regulation": { "title": "Admin regulation", "context": None }, }) self.api.set_user(self.users['reader']) response = self.api.post(all_models.Policy, { "policy": { "title": "reader Policy", "context": None }, }) response, _ = self.api.search("Regulation,Policy") entries = response.json["results"]["entries"] self.assertEqual(len(entries), 2) response, _ = self.api.search("Regulation,Policy", counts=True) self.assertEqual(response.json["results"]["counts"]["Policy"], 1) self.assertEqual(response.json["results"]["counts"]["Regulation"], 1) def _get_count(self, obj): """ Return the number of counts for the given object from search """ response, _ = self.api.search(obj, counts=True) return response.json["results"]["counts"].get(obj) def test_reader_should_see_users(self): """ Test if creator can see all the users in the system """ self.api.set_user(self.users['admin']) admin_count = self._get_count("Person") self.api.set_user(self.users['reader']) reader_count = self._get_count("Person") self.assertEqual(admin_count, reader_count) def test_relationships_access(self): """Check if reader can access relationship objects""" self.api.set_user(self.users['admin']) _, first_regulation = self.object_generator.generate_object( all_models.Regulation, data={"regulation": { "title": "Test regulation", "context": None }}) _, second_regulation = self.object_generator.generate_object( all_models.Regulation, data={ "regulation": { "title": "Test regulation 2", "context": None } }) response, rel = self.object_generator.generate_relationship( first_regulation, second_regulation) self.assertStatus(response, 201) self.api.set_user(self.users['reader']) response = self.api.get_collection(all_models.Relationship, rel.id) self.assert200(response) num = len(response.json["relationships_collection"]["relationships"]) self.assertEqual(num, 1) def test_creation_of_mappings(self): """Check if reader can't create mappings""" self.object_generator.api.set_user(self.users["admin"]) _, control = self.object_generator.generate_object( all_models.Control, data={"control": { "title": "Test Control", "context": None }}) self.object_generator.api.set_user(self.users['reader']) _, program = self.object_generator.generate_object( all_models.Program, data={"program": { "title": "Test Program", "context": None }}) response, _ = self.object_generator.generate_relationship( control, program, program.context) self.assert403(response) @ddt.data("creator", "reader") def test_unmap_people(self, user_role): """Test that global reader/creator can't unmap people from program""" user = self.users[user_role] with factories.single_commit(): program = factories.ProgramFactory() mapped_person = factories.ObjectPersonFactory( personable=program, person=user, context=program.context) self.api.set_user(user) db.session.add(mapped_person) response = self.api.delete(mapped_person) self.assert403(response) def test_read_evidence_revision(self): """Global Read can read Evidence revision content""" user = self.users["reader"] link = "google.com" evidence = factories.EvidenceUrlFactory(link=link) evidence_id = evidence.id self.api.set_user(user) resp = self.api.client.get( "/api/revisions?resource_type={}&resource_id={}".format( evidence.type, evidence_id)) rev_content = resp.json["revisions_collection"]["revisions"][0][ "content"] self.assertTrue(rev_content) self.assertEquals(link, rev_content["link"])
class TestPermissionsOnAssessmentTemplate(TestCase): """ Test check permissions for ProgramEditor on get and post assessment_temaplte action""" def setUp(self): super(TestPermissionsOnAssessmentTemplate, self).setUp() self.api = Api() self.generator = ObjectGenerator() _, program = self.generator.generate_object(all_models.Program) program_id = program.id _, self.editor = self.generator.generate_person(user_role="Creator") role = perms.all_models.Role.query.filter( perms.all_models.Role.name == "ProgramEditor").first() self.generator.generate_user_role( self.editor, role, all_models.Program.query.get(program_id)) _, audit = self.generator.generate_object( all_models.Audit, { "title": "Audit", "program": { "id": program_id }, "status": "Planned" }, ) audit_id = audit.id generated_at = self.generator.generate_object( all_models.AssessmentTemplate, { "title": "Template", "_NON_RELEVANT_OBJ_TYPES": {}, "_objectTypes": {}, "audit": { "id": audit.id }, "audit_title": audit.title, "people_value": [], "default_people": { "assignees": "Admin", "verifiers": "Admin", }, "context": { "id": audit.context.id }, }) self.assessment_template_resp, assessment_template = generated_at assessment_template_id = assessment_template.id self.api.set_user(self.editor) self.perms_data = self.api.client.get("/permissions").json self.audit = all_models.Audit.query.get(audit_id) self.assessment_template = all_models.AssessmentTemplate.query.get( assessment_template_id) def test_post_action(self): """Test create action on AssessmentTemplate created by api""" data = [{ "assessment_template": { "_NON_RELEVANT_OBJ_TYPES": {}, "_objectTypes": {}, "audit": { "id": self.audit.id }, "audit_title": self.audit.title, "people_value": [], "default_people": { "assignees": "Admin", "verifiers": "Admin", }, "context": { "id": self.audit.context.id }, "title": "123", } }] self.api.set_user(self.editor) resp = self.api.post(all_models.AssessmentTemplate, data) self.assert200(resp) def test_get_action(self): """Test read action on AssessmentTemplate created by api""" resp = self.api.get(all_models.AssessmentTemplate, self.assessment_template.id) self.assert200(resp) def test_put_action(self): """Test update action on AssessmentTemplate created by api""" to_update = copy.deepcopy(self.assessment_template_resp.json) new_title = "new_{}".format(self.assessment_template.title) to_update['assessment_template']['title'] = new_title resp = self.api.put(self.assessment_template, to_update) self.assert200(resp) assessment_tmpl = all_models.AssessmentTemplate.query.get( self.assessment_template.id) self.assertEqual(new_title, assessment_tmpl.title) def test_delete_action(self): """Test delete action on AssessmentTemplate created by api""" resp = self.api.delete(self.assessment_template) self.assert200(resp) self.assertFalse( all_models.AssessmentTemplate.query.filter( all_models.AssessmentTemplate == self.assessment_template.id).all())
class TestResource(TestCase): """ Test /search REST API """ def setUp(self): super(TestResource, self).setUp() self.api = Api() self.object_generator = ObjectGenerator() self.create_objects() def create_objects(self): """Create objects to be searched. Creates five controls and makes relationships. 0 1 2 3 4 |---| |---| | |-------|-------| """ self.objects = [ self.object_generator.generate_object(Control)[1].id for _ in xrange(5) ] self.objects = Control.eager_query().filter( Control.id.in_(self.objects)).all() for src, dst in [(0, 1), (0, 2), (2, 3), (2, 4)]: self.object_generator.generate_relationship( self.objects[src], self.objects[dst]) def search(self, *args, **kwargs): res, _ = self.api.search(*args, **kwargs) return res.json["results"]["entries"] def test_search_all(self): """Test search for all objects of a type.""" res, _ = self.api.search("Control") self.assertEqual(len(res.json["results"]["entries"]), 5) def test_search_query(self): """Test search with query by title.""" entries = self.search("Control", query=self.objects[0].title) self.assertEqual({entry["id"] for entry in entries}, {self.objects[0].id}) def test_search_relevant(self): """Test search with 'relevant to' single object.""" relevant_objects = "Control:{}".format(self.objects[0].id) entries = self.search("Control", relevant_objects=relevant_objects) self.assertEqual({entry["id"] for entry in entries}, {self.objects[i].id for i in [1, 2]}) def test_search_relevant_multi(self): """Test search with 'relevant to' multiple objects.""" ids = ",".join("Control:{}".format(self.objects[i].id) for i in (0, 3)) entries = self.search("Control", relevant_objects=ids) self.assertEqual({entry["id"] for entry in entries}, {self.objects[2].id}) def test_search_fail_with_terms_none(self): """Test search to fail with BadRequest (400 Error) when terms are None.""" query = '/search?types={}&counts_only={}'.format("Control", False) response = self.api.client.get(query) self.assert400(response) self.assertEqual( response.json['message'], 'Query parameter "q" ' 'specifying search terms must be provided.')
class TestResource(TestCase): """ Test /search REST API """ def setUp(self): super(TestResource, self).setUp() self.api = Api() self.object_generator = ObjectGenerator() self.create_objects() def create_objects(self): """Create objects to be searched. Creates five controls and makes relationships. 0 1 2 3 4 |---| |---| | |-------|-------| """ self.objects = [ self.object_generator.generate_object(Control)[1].id for _ in xrange(5) ] self.objects = Control.eager_query().filter( Control.id.in_(self.objects) ).all() for src, dst in [(0, 1), (0, 2), (2, 3), (2, 4)]: self.object_generator.generate_relationship( self.objects[src], self.objects[dst] ) def search(self, *args, **kwargs): res, _ = self.api.search(*args, **kwargs) return res.json["results"]["entries"] def test_search_all(self): """Test search for all objects of a type.""" res, _ = self.api.search("Control") self.assertEqual(len(res.json["results"]["entries"]), 5) def test_search_query(self): """Test search with query by title.""" entries = self.search("Control", query=self.objects[0].title) self.assertEqual({entry["id"] for entry in entries}, {self.objects[0].id}) def test_search_relevant(self): """Test search with 'relevant to' single object.""" relevant_objects = "Control:{}".format(self.objects[0].id) entries = self.search("Control", relevant_objects=relevant_objects) self.assertEqual({entry["id"] for entry in entries}, {self.objects[i].id for i in [1, 2]}) def test_search_relevant_multi(self): """Test search with 'relevant to' multiple objects.""" ids = ",".join("Control:{}".format(self.objects[i].id) for i in (0, 3)) entries = self.search("Control", relevant_objects=ids) self.assertEqual({entry["id"] for entry in entries}, {self.objects[2].id}) def test_search_fail_with_terms_none(self): """Test search to fail with BadRequest (400 Error) when terms are None.""" query = '/search?types={}&counts_only={}'.format("Control", False) response = self.api.client.get(query) self.assert400(response) self.assertEqual(response.json['message'], 'Query parameter "q" ' 'specifying search terms must be provided.')
class TestPermissionsOnAssessmentTemplate(TestCase): """ Test check permissions for ProgramEditor on get and post assessment_temaplte action""" def setUp(self): super(TestPermissionsOnAssessmentTemplate, self).setUp() self.api = Api() self.generator = ObjectGenerator() _, program = self.generator.generate_object(all_models.Program) program_id = program.id _, self.editor = self.generator.generate_person( user_role="Creator" ) role = perms.all_models.Role.query.filter( perms.all_models.Role.name == "ProgramEditor" ).first() self.generator.generate_user_role( self.editor, role, all_models.Program.query.get(program_id) ) _, audit = self.generator.generate_object( all_models.Audit, { "title": "Audit", "program": {"id": program_id}, "status": "Planned" }, ) audit_id = audit.id generated_at = self.generator.generate_object( all_models.AssessmentTemplate, { "title": "Template", "_NON_RELEVANT_OBJ_TYPES": {}, "_objectTypes": {}, "audit": {"id": audit.id}, "audit_title": audit.title, "people_value": [], "default_people": { "assessors": "Object Owners", "verifiers": "Object Owners", }, "context": {"id": audit.context.id}, } ) self.assessment_template_resp, assessment_template = generated_at assessment_template_id = assessment_template.id self.api.set_user(self.editor) self.perms_data = self.api.client.get("/permissions").json self.audit = all_models.Audit.query.get(audit_id) self.assessment_template = all_models.AssessmentTemplate.query.get( assessment_template_id) def test_post_action(self): """Test create action on AssessmentTemplate created by api""" data = [{ "assessment_template": { "_NON_RELEVANT_OBJ_TYPES": {}, "_objectTypes": {}, "audit": {"id": self.audit.id}, "audit_title": self.audit.title, "people_value": [], "default_people": { "assessors": "Object Owners", "verifiers": "Object Owners", }, "context": {"id": self.audit.context.id}, "title": "123", } }] self.api.set_user(self.editor) resp = self.api.post(all_models.AssessmentTemplate, data) self.assert200(resp) def test_get_action(self): """Test read action on AssessmentTemplate created by api""" resp = self.api.get(all_models.AssessmentTemplate, self.assessment_template.id) self.assert200(resp) def test_put_action(self): """Test update action on AssessmentTemplate created by api""" to_update = copy.deepcopy(self.assessment_template_resp.json) new_title = "new_{}".format(self.assessment_template.title) to_update['assessment_template']['title'] = new_title resp = self.api.put(self.assessment_template, to_update) self.assert200(resp) assessment_tmpl = all_models.AssessmentTemplate.query.get( self.assessment_template.id ) self.assertEqual(new_title, assessment_tmpl.title) def test_delete_action(self): """Test delete action on AssessmentTemplate created by api""" resp = self.api.delete(self.assessment_template) self.assert200(resp) self.assertFalse(all_models.AssessmentTemplate.query.filter( all_models.AssessmentTemplate == self.assessment_template.id).all())
class TestReader(TestCase): """ Test reader role """ def setUp(self): super(TestReader, self).setUp() self.api = Api() self.object_generator = ObjectGenerator() self.init_users() def init_users(self): """ Init users needed by the test cases """ users = [("reader", "Reader"), ("admin", "Administrator"), ("creator", "Creator")] self.users = {} for (name, role) in users: _, user = self.object_generator.generate_person( data={"name": name}, user_role=role) self.users[name] = user self.users["external"] = self.object_generator.generate_person( data={"email": "*****@*****.**"})[1] def test_admin_page_access(self): """Only admin can use admin requirement""" for role, code in (("reader", 403), ("admin", 200)): self.api.set_user(self.users[role]) self.assertEqual(self.api.client.get("/admin").status_code, code) def test_reader_can_crud(self): """ Test Basic create/read,update/delete operations """ self.api.set_user(self.users["reader"]) all_errors = [] base_models = set([ "DataAsset", "Contract", "Policy", "Regulation", "Standard", "Document", "Facility", "Market", "Objective", "OrgGroup", "Vendor", "Product", "System", "Process", "Project", "AccessGroup", "Metric", "TechnologyEnvironment", "ProductGroup", "KeyReport", "AccountBalance", ]) for model_singular in base_models: try: model = get_model(model_singular) table_singular = model._inflector.table_singular table_plural = model._inflector.table_plural # Test POST creation response, _ = self.object_generator.generate_object( model, data={ table_singular: { "title": model_singular, "context": None, "documents_reference_url": "ref", "link": "https://example.com", # only for Document "contact": { "type": "Person", "id": self.users["reader"].id, } }, } ) if response.status_code != 201: all_errors.append("{} post creation failed {} {}".format( model_singular, response.status, response.data)) continue obj_id = response.json.get(table_singular).get("id") # Test GET when owner response = self.api.get(model, obj_id) if response.status_code != 200: all_errors.append("{} can't GET object {}".format( model_singular, response.status)) continue # Test GET collection when owner response = self.api.get_collection(model, obj_id) collection = response.json.get( "{}_collection".format(table_plural)).get(table_plural) if not collection: all_errors.append( "{} cannot retrieve object even if owner (collection)".format( model_singular)) continue except: all_errors.append("{} exception thrown".format(model_singular)) raise self.assertEqual(all_errors, []) def test_reader_search(self): """ Test if reader can see the correct object while using search api """ self.api.set_user(self.users['admin']) self.api.post(all_models.Regulation, { "regulation": {"title": "Admin regulation", "context": None}, }) self.api.set_user(self.users['reader']) response = self.api.post(all_models.Policy, { "policy": {"title": "reader Policy", "context": None}, }) response, _ = self.api.search("Regulation,Policy") entries = response.json["results"]["entries"] self.assertEqual(len(entries), 2) response, _ = self.api.search("Regulation,Policy", counts=True) self.assertEqual(response.json["results"]["counts"]["Policy"], 1) self.assertEqual(response.json["results"]["counts"]["Regulation"], 1) def _get_count(self, obj): """ Return the number of counts for the given object from search """ response, _ = self.api.search(obj, counts=True) return response.json["results"]["counts"].get(obj) def test_reader_should_see_users(self): """ Test if creator can see all the users in the system """ self.api.set_user(self.users['admin']) admin_count = self._get_count("Person") self.api.set_user(self.users['reader']) reader_count = self._get_count("Person") self.assertEqual(admin_count, reader_count) def test_relationships_access(self): """Check if reader can access relationship objects""" self.api.set_user(self.users['admin']) _, first_regulation = self.object_generator.generate_object( all_models.Regulation, data={"regulation": {"title": "Test regulation", "context": None}} ) _, second_regulation = self.object_generator.generate_object( all_models.Regulation, data={"regulation": {"title": "Test regulation 2", "context": None}} ) response, rel = self.object_generator.generate_relationship( first_regulation, second_regulation ) self.assertStatus(response, 201) self.api.set_user(self.users['reader']) response = self.api.get_collection(all_models.Relationship, rel.id) self.assert200(response) num = len(response.json["relationships_collection"]["relationships"]) self.assertEqual(num, 1) def test_creation_of_mappings(self): """Check if reader can't create mappings""" self.object_generator.api.set_user(self.users["external"]) _, control = self.object_generator.generate_object( all_models.Control, data={"control": {"title": "Test Control", "context": None}} ) self.object_generator.api.set_user(self.users['reader']) _, program = self.object_generator.generate_object( all_models.Program, data={"program": {"title": "Test Program", "context": None}} ) response, _ = self.object_generator.generate_relationship( control, program, program.context ) self.assert403(response) @ddt.data("creator", "reader") def test_unmap_people(self, user_role): """Test that global reader/creator can't unmap people from program""" user = self.users[user_role] with factories.single_commit(): program = factories.ProgramFactory() mapped_person = factories.ObjectPersonFactory( personable=program, person=user, context=program.context ) self.api.set_user(user) db.session.add(mapped_person) response = self.api.delete(mapped_person) self.assert403(response) def test_read_evidence_revision(self): """Global Read can read Evidence revision content""" user = self.users["reader"] link = "google.com" evidence = factories.EvidenceUrlFactory(link=link) evidence_id = evidence.id self.api.set_user(user) resp = self.api.client.get( "/api/revisions?resource_type={}&resource_id={}".format(evidence.type, evidence_id)) rev_content = resp.json["revisions_collection"]["revisions"][0]["content"] self.assertTrue(rev_content) self.assertEquals(link, rev_content["link"])
class TestCreator(TestCase): """ TestCreator """ def setUp(self): super(TestCreator, self).setUp() self.api = Api() self.object_generator = ObjectGenerator() self.init_users() def init_users(self): """ Init users needed by the test cases """ users = [("creator", "Creator"), ("admin", "Administrator")] self.users = {} for (name, role) in users: _, user = self.object_generator.generate_person( data={"name": name}, user_role=role) self.users[name] = user def test_admin_page_access(self): """Permissions to admin page.""" for role, code in (("creator", 403), ("admin", 200)): self.api.set_user(self.users[role]) self.assertEqual(self.api.client.get("/admin").status_code, code) def test_creator_can_crud(self): """ Test Basic create/read,update/delete operations """ self.api.set_user(self.users["creator"]) creator_id = self.users["creator"].id audit_id = factories.AuditFactory().id all_errors = [] base_models = { "Control", "DataAsset", "Contract", "Requirement", "Policy", "Regulation", "Standard", "Document", "Facility", "Market", "Objective", "OrgGroup", "Vendor", "Product", "System", "Process", "Project", "AccessGroup", "Metric", "ProductGroup", "TechnologyEnvironment", } for model_singular in base_models: try: model = get_model(model_singular) table_singular = model._inflector.table_singular table_plural = model._inflector.table_plural # Test POST creation response, _ = self.object_generator.generate_object( model, data={ table_singular: { "title": model_singular, "context": None, "documents_reference_url": "ref", # ignored except for Document "link": "https://example.com", "contact": { "type": "Person", "id": creator_id }, # this is ignored on everything but Issues "audit": { "id": audit_id, "type": "Audit", } }, }) if response.status_code != 201: all_errors.append("{} post creation failed {} {}".format( model_singular, response.status, response.data)) continue # Test GET when not owner obj_id = response.json.get(table_singular).get("id") response = self.api.get(model, obj_id) if response.status_code != 403: # we are not onwers yet all_errors.append( "{} can retrieve object if not owner".format( model_singular)) continue response = self.api.get_collection(model, obj_id) collection = response.json.get( "{}_collection".format(table_plural)).get(table_plural) if collection: all_errors.append( "{} can retrieve object if not owner (collection)". format(model_singular)) continue # Test GET when owner acr = all_models.AccessControlRole.query.filter_by( object_type=model_singular, name="Admin").one() acl = all_models.AccessControlList.query.filter_by( object_id=obj_id, object_type=model_singular, ac_role=acr, ).one() factories.AccessControlPersonFactory( ac_list=acl, person_id=creator_id, ) response = self.api.get(model, obj_id) if response.status_code != 200: all_errors.append("{} can't GET object {}".format( model_singular, response.status)) continue # Test GET collection when owner response = self.api.get_collection(model, obj_id) collection = response.json.get( "{}_collection".format(table_plural)).get(table_plural) if not collection: all_errors.append( "{} cannot retrieve object even if owner (collection)". format(model_singular)) continue except: all_errors.append("{} exception thrown".format(model_singular)) raise self.assertEqual(all_errors, []) def test_creator_search(self): """Test if creator can see the correct object while using the search api""" self.api.set_user(self.users['admin']) self.api.post(all_models.Regulation, { "regulation": { "title": "Admin regulation", "context": None }, }) self.api.set_user(self.users['creator']) acr_id = all_models.AccessControlRole.query.filter_by( object_type="Policy", name="Admin").first().id response = self.api.post( all_models.Policy, { "policy": { "title": "Creator Policy", "context": None, "access_control_list": [ acl_helper.get_acl_json(acr_id, self.users["creator"].id) ], }, }) response.json.get("policy").get("id") response, _ = self.api.search("Regulation,Policy") entries = response.json["results"]["entries"] self.assertEqual(len(entries), 1) self.assertEqual(entries[0]["type"], "Policy") response, _ = self.api.search("Regulation,Policy", counts=True) self.assertEqual(response.json["results"]["counts"]["Policy"], 1) self.assertEqual(response.json["results"]["counts"].get("Regulation"), None) def _get_count(self, obj): """ Return the number of counts for the given object from search """ response, _ = self.api.search(obj, counts=True) return response.json["results"]["counts"].get(obj) def test_creator_should_see_users(self): """ Test if creator can see all the users in the system """ self.api.set_user(self.users['admin']) admin_count = self._get_count("Person") self.api.set_user(self.users['creator']) creator_count = self._get_count("Person") self.assertEqual(admin_count, creator_count) def test_relationships_access(self): """Check if creator cannot access relationship objects""" self.api.set_user(self.users['admin']) _, first_regulation = self.object_generator.generate_object( all_models.Regulation, data={"regulation": { "title": "Test regulation", "context": None }}) _, second_regulation = self.object_generator.generate_object( all_models.Regulation, data={ "regulation": { "title": "Test regulation 2", "context": None } }) response, rel = self.object_generator.generate_relationship( first_regulation, second_regulation) relationship_id = rel.id self.assertEqual(response.status_code, 201) self.api.set_user(self.users['creator']) response = self.api.get_collection(all_models.Relationship, relationship_id) self.assertEqual(response.status_code, 200) num = len(response.json["relationships_collection"]["relationships"]) self.assertEqual(num, 0) def test_revision_access(self): """Check if creator can access the right revision objects.""" def gen(title, extra_data=None): """Generates requirement.""" requirement_content = {"title": title, "context": None} if extra_data: requirement_content.update(**extra_data) return self.object_generator.generate_object( all_models.Requirement, data={"requirement": requirement_content})[1] def check(obj, expected): """Check that how many revisions of an object current user can see.""" response = self.api.get_query( all_models.Revision, "resource_type={}&resource_id={}".format(obj.type, obj.id)) self.assertEqual(response.status_code, 200) self.assertEqual( len(response.json['revisions_collection']['revisions']), expected) self.api.set_user(self.users["admin"]) obj_1 = gen("Test Requirement 1") self.api.set_user(self.users["creator"]) acr_id = all_models.AccessControlRole.query.filter_by( object_type="Requirement", name="Admin").first().id linked_acl = { "access_control_list": [acl_helper.get_acl_json(acr_id, self.users["creator"].id)], } check(obj_1, 0) obj_2 = gen("Test Requirement 2", linked_acl) obj2_acl = obj_2.access_control_list[0][1] check(obj_2, 1) check(obj2_acl, 1) @ddt.data("creator", "admin") def test_count_type_in_accordion(self, glob_role): """Return count of Persons in DB for side accordion.""" self.api.set_user(self.users[glob_role]) ocordion_api_person_count_link = ( "/search?" "q=&types=Program%2CWorkflow_All%2C" "Audit%2CAssessment%2CIssue%2CRegulation%2C" "Policy%2CStandard%2CContract%2CRequirement%2CControl%2C" "Objective%2CPerson%2COrgGroup%2CVendor%2CAccessGroup%2CSystem%2C" "Process%2CDataAsset%2CProduct%2CProject%2CFacility%2C" "Market%2CRisk%2CThreat&counts_only=true&" "extra_columns=Workflow_All%3DWorkflow%2C" "Workflow_Active%3DWorkflow%2CWorkflow_Draft%3D" "Workflow%2CWorkflow_Inactive%3DWorkflow&contact_id=1&" "extra_params=Workflow%3Astatus%3DActive%3BWorkflow_Active" "%3Astatus%3DActive%3BWorkflow_Inactive%3Astatus%3D" "Inactive%3BWorkflow_Draft%3Astatus%3DDraft") resp = self.api.client.get(ocordion_api_person_count_link) self.assertIn("Person", resp.json["results"]["counts"]) self.assertEqual(all_models.Person.query.count(), resp.json["results"]["counts"]["Person"]) @ddt.data( ("/api/revisions?resource_type={}&resource_id={}", 1), ("/api/revisions?source_type={}&source_id={}", 0), ("/api/revisions?destination_type={}&destination_id={}", 1), ) @ddt.unpack def test_changelog_access(self, link, revision_count): """Test accessing changelog under GC user who is assigned to object""" with factories.single_commit(): audit = factories.AuditFactory() asmnt = factories.AssessmentFactory(audit=audit) asmnt_id = asmnt.id factories.RelationshipFactory(source=audit, destination=asmnt) factories.AccessControlPersonFactory( ac_list=asmnt.acr_name_acl_map["Verifiers"], person=self.users["creator"], ) self.api.set_user(self.users["creator"]) response = self.api.client.get(link.format("Assessment", asmnt_id)) self.assert200(response) self.assertEqual( len( response.json.get("revisions_collection", {}).get("revisions")), revision_count) @ddt.data(all_models.ControlCategory, all_models.ControlAssertion) def test_permissions_for_categories(self, category_model): """Test get collection for {0}.""" self.api.set_user(self.users["creator"]) resp = self.api.get_collection(category_model, None) plural_name = category_model._inflector.table_plural key_name = "{}_collection".format(plural_name) self.assertIn(key_name, resp.json) self.assertIn(plural_name, resp.json[key_name]) collection = resp.json[key_name][plural_name] self.assertTrue(collection, "Collection shouldn't be empty")
class TestWithReadOnlyAccessAPI(TestCase): """Test WithReadOnlyAccess mixin""" def setUp(self): super(TestWithReadOnlyAccessAPI, self).setUp() self.object_generator = ObjectGenerator() self.object_generator.api.login_as_normal() @ddt.data( ('System', True), ('System', False), ('System', None), ('System', "qwert"), ) @ddt.unpack def test_readonly_ignored_on_post(self, obj_type, readonly): """Test flag readonly ignored on object {0} POST for body readonly={1}""" dct = dict() if readonly is not None: dct['readonly'] = readonly resp, obj = self.object_generator.generate_object( get_model(obj_type), {'readonly': readonly}, ) self.assertStatus(resp, 201) self.assertFalse(obj.readonly) @ddt.data( ('System', False, False, 200), ('System', False, True, 200), ('System', False, None, 200), ('System', True, False, 405), ('System', True, True, 405), ('System', True, None, 405), ) @ddt.unpack def test_put(self, obj_type, current, new, exp_code): """Test {0} PUT readonly={2} for current readonly={1}""" factory = factories.get_model_factory(obj_type) with factories.single_commit(): obj = factory(title='a', readonly=current) obj_id = obj.id data = {'title': 'b'} if new is not None: data['readonly'] = new resp = self.object_generator.api.put(obj, data) self.assertStatus(resp, exp_code) obj = get_model(obj_type).query.get(obj_id) self.assertEqual(obj.readonly, current) @ddt.data('System') def test_403_if_put_readonly_without_perms(self, obj_type): """Test {0} with readonly=True PUT returns 401 instead of 405 This test ensures that user without permission for the object cannot obtain value for flag readonly """ role_obj = all_models.Role.query.filter( all_models.Role.name == "Creator").one() factory = factories.get_model_factory(obj_type) with factories.single_commit(): # create Global Creator person = factories.PersonFactory() person_id = person.id rbac_factories.UserRoleFactory(role=role_obj, person=person) # Create object obj = factory(title='a', readonly=True) obj_id = obj.id self.object_generator.api.set_user(all_models.Person.query.get(person_id)) obj = get_model(obj_type).query.get(obj_id) resp = self.object_generator.api.put(obj, {'title': 'b'}) self.assert403(resp) @ddt.data( ('System', False, 200, True), ('System', True, 405, False), ) @ddt.unpack def test_delete(self, obj_type, readonly, exp_code, exp_deleted): """Test {0} DELETE if readonly={1}""" factory = factories.get_model_factory(obj_type) with factories.single_commit(): obj = factory(title='a', readonly=readonly) obj_id = obj.id resp = self.object_generator.api.delete(obj) self.assertStatus(resp, exp_code) obj = get_model(obj_type).query.get(obj_id) if exp_deleted: self.assertIsNone(obj) else: self.assertIsNotNone(obj) @ddt.data('System') def test_403_if_delete_readonly_without_perms(self, obj_type): """Test {0} with readonly=True DELETE returns 401 This test ensures that user without permission for the object cannot obtain value for flag readonly """ role_obj = all_models.Role.query.filter( all_models.Role.name == "Creator").one() factory = factories.get_model_factory(obj_type) with factories.single_commit(): # create Global Creator person = factories.PersonFactory() person_id = person.id rbac_factories.UserRoleFactory(role=role_obj, person=person) # Create object obj = factory(title='a', readonly=True) obj_id = obj.id self.object_generator.api.set_user(all_models.Person.query.get(person_id)) obj = get_model(obj_type).query.get(obj_id) resp = self.object_generator.api.delete(obj) self.assert403(resp) obj = get_model(obj_type).query.get(obj_id) self.assertIsNotNone(obj) @ddt.data( ('System', False, 'Document', True, 201), ('System', False, 'Document', False, 201), ('System', True, 'Document', True, 405), ('System', True, 'Document', False, 405), ('System', False, 'Comment', True, 201), ('System', False, 'Comment', False, 201), ('System', True, 'Comment', True, 201), ('System', True, 'Comment', False, 201), ) @ddt.unpack def test_relationship_post(self, obj_type, readonly, rel_obj_type, swap, expected_code): """Test PUT relationship {0}.readonly={1}, related object type {2}""" factory = factories.get_model_factory(obj_type) rel_factory = factories.get_model_factory(rel_obj_type) with factories.single_commit(): obj = factory(title='a', readonly=readonly) rel_obj = rel_factory() if swap: source, destination = rel_obj, obj else: source, destination = obj, rel_obj resp, _ = self.object_generator.generate_relationship( source=source, destination=destination ) self.assertStatus(resp, expected_code) @ddt.data( ('System', False, 'Document', True, 200), ('System', False, 'Document', False, 200), ('System', True, 'Document', True, 405), ('System', True, 'Document', False, 405), ('System', False, 'Comment', True, 200), ('System', False, 'Comment', False, 200), ('System', True, 'Comment', True, 200), ('System', True, 'Comment', False, 200), ) @ddt.unpack def test_relationship_delete(self, obj_type, readonly, rel_obj_type, swap, expected_code): """Test DELETE relationship {0}.readonly={1}, related object type {2}""" factory = factories.get_model_factory(obj_type) rel_factory = factories.get_model_factory(rel_obj_type) with factories.single_commit(): obj = factory(title='a', readonly=readonly) rel_obj = rel_factory() if swap: source, destination = rel_obj, obj else: source, destination = obj, rel_obj robj = factories.RelationshipFactory(source=source, destination=destination) resp = self.object_generator.api.delete(robj) self.assertStatus(resp, expected_code)
class TestWithReadOnlyAccessAPI(TestCase, query_helper.WithQueryApi): """Test WithReadOnlyAccess mixin""" def setUp(self): super(TestWithReadOnlyAccessAPI, self).setUp() self.object_generator = ObjectGenerator() self.object_generator.api.login_as_normal() @ddt.data( ('System', True), ('System', False), ('System', None), ('System', _NOT_SPECIFIED), ('System', "qwert"), ) @ddt.unpack def test_readonly_ignored_on_post(self, obj_type, readonly): """Test flag readonly ignored on object {0} POST for body readonly={1}""" dct = dict() if readonly is not _NOT_SPECIFIED: dct['readonly'] = readonly resp, obj = self.object_generator.generate_object( get_model(obj_type), dct, ) self.assertStatus(resp, 201) self.assertFalse(obj.readonly) @ddt.data( ('System', True, True), ('System', False, False), ('System', None, False), ('System', _NOT_SPECIFIED, False), ) @ddt.unpack def test_readonly_set_on_post_as_external(self, obj_type, readonly, result): """Test flag readonly on {0} POST for body readonly={1} as external user""" dct = dict() if readonly is not _NOT_SPECIFIED: dct['readonly'] = readonly with self.object_generator.api.as_external(): resp, obj = self.object_generator.generate_object( get_model(obj_type), dct, ) obj_id = obj.id self.assertStatus(resp, 201) obj = get_model(obj_type).query.get(obj_id) self.assertEqual(obj.readonly, result) @ddt.data( ('System', False, False, 200), ('System', False, True, 200), ('System', False, None, 200), ('System', False, _NOT_SPECIFIED, 200), ('System', False, "qwerty", 200), ('System', True, False, 405), ('System', True, True, 405), ('System', True, None, 405), ('System', True, _NOT_SPECIFIED, 405), ('System', True, "qwerty", 405), ) @ddt.unpack def test_put(self, obj_type, current, new, exp_code): """Test {0} PUT readonly={2} for current readonly={1}""" factory = factories.get_model_factory(obj_type) with factories.single_commit(): obj = factory(title='a', readonly=current) obj_id = obj.id data = {'title': 'b'} if new is not _NOT_SPECIFIED: data['readonly'] = new resp = self.object_generator.api.put(obj, data) self.assertStatus(resp, exp_code) obj = get_model(obj_type).query.get(obj_id) self.assertEqual(obj.readonly, current) @ddt.data( ('System', False, False, 200, False), ('System', False, True, 200, True), ('System', False, None, 200, False), ('System', False, _NOT_SPECIFIED, 200, False), ('System', True, False, 200, False), ('System', True, True, 200, True), ('System', True, None, 200, True), ('System', True, _NOT_SPECIFIED, 200, True), ) @ddt.unpack def test_put_as_external(self, obj_type, current, new, exp_code, exp_readonly): """Test {0} PUT readonly={2} for current readonly={1} for external user""" factory = factories.get_model_factory(obj_type) with factories.single_commit(): obj = factory(title='a', readonly=current) obj_id = obj.id data = {'title': 'b'} if new is not _NOT_SPECIFIED: data['readonly'] = new with self.object_generator.api.as_external(): obj = get_model(obj_type).query.get(obj_id) resp = self.object_generator.api.put(obj, data) self.assertStatus(resp, exp_code) obj = get_model(obj_type).query.get(obj_id) self.assertEqual(obj.readonly, exp_readonly) @ddt.data('System') def test_403_if_put_readonly_without_perms(self, obj_type): """Test {0} with readonly=True PUT returns 401 instead of 405 This test ensures that user without permission for the object cannot obtain value for flag readonly """ role_obj = all_models.Role.query.filter( all_models.Role.name == "Creator").one() factory = factories.get_model_factory(obj_type) with factories.single_commit(): # create Global Creator person = factories.PersonFactory() person_id = person.id rbac_factories.UserRoleFactory(role=role_obj, person=person) # Create object obj = factory(title='a', readonly=True) obj_id = obj.id self.object_generator.api.set_user( all_models.Person.query.get(person_id)) obj = get_model(obj_type).query.get(obj_id) resp = self.object_generator.api.put(obj, {'title': 'b'}) self.assert403(resp) @ddt.data( ('System', True, False, 200, True), ('System', True, True, 405, False), ('System', False, False, 200, True), ('System', False, True, 405, False), ) @ddt.unpack def test_delete(self, obj_type, is_external, readonly, exp_code, exp_deleted): """Test {0} DELETE if readonly={1}""" factory = factories.get_model_factory(obj_type) with factories.single_commit(): obj = factory(title='a', readonly=readonly) obj_id = obj.id if is_external: self.object_generator.api.login_as_external() else: self.object_generator.api.login_as_normal() obj = get_model(obj_type).query.get(obj_id) resp = self.object_generator.api.delete(obj) self.assertStatus(resp, exp_code) obj = get_model(obj_type).query.get(obj_id) if exp_deleted: self.assertIsNone(obj) else: self.assertIsNotNone(obj) @ddt.data('System') def test_403_if_delete_readonly_without_perms(self, obj_type): """Test {0} with readonly=True DELETE returns 401 This test ensures that user without permission for the object cannot obtain value for flag readonly """ role_obj = all_models.Role.query.filter( all_models.Role.name == "Creator").one() factory = factories.get_model_factory(obj_type) with factories.single_commit(): # create Global Creator person = factories.PersonFactory() person_id = person.id rbac_factories.UserRoleFactory(role=role_obj, person=person) # Create object obj = factory(title='a', readonly=True) obj_id = obj.id self.object_generator.api.set_user( all_models.Person.query.get(person_id)) obj = get_model(obj_type).query.get(obj_id) resp = self.object_generator.api.delete(obj) self.assert403(resp) obj = get_model(obj_type).query.get(obj_id) self.assertIsNotNone(obj) @ddt.data( ('System', False, 'Document', True, 201), ('System', False, 'Document', False, 201), ('System', True, 'Document', True, 405), ('System', True, 'Document', False, 405), ('System', False, 'Comment', True, 201), ('System', False, 'Comment', False, 201), ('System', True, 'Comment', True, 201), ('System', True, 'Comment', False, 201), ) @ddt.unpack def test_relationship_post(self, obj_type, readonly, rel_obj_type, swap, expected_code): """Test PUT relationship {0}.readonly={1}, related object type {2}""" factory = factories.get_model_factory(obj_type) rel_factory = factories.get_model_factory(rel_obj_type) with factories.single_commit(): obj = factory(title='a', readonly=readonly) rel_obj = rel_factory() if swap: source, destination = rel_obj, obj else: source, destination = obj, rel_obj resp, _ = self.object_generator.generate_relationship( source=source, destination=destination) self.assertStatus(resp, expected_code) @ddt.data( ('System', False, 'Document', True, 200), ('System', False, 'Document', False, 200), ('System', True, 'Document', True, 405), ('System', True, 'Document', False, 405), ('System', False, 'Comment', True, 200), ('System', False, 'Comment', False, 200), ('System', True, 'Comment', True, 200), ('System', True, 'Comment', False, 200), ) @ddt.unpack def test_relationship_delete(self, obj_type, readonly, rel_obj_type, swap, expected_code): """Test DELETE relationship {0}.readonly={1}, related object type {2}""" factory = factories.get_model_factory(obj_type) rel_factory = factories.get_model_factory(rel_obj_type) with factories.single_commit(): obj = factory(title='a', readonly=readonly) rel_obj = rel_factory() if swap: source, destination = rel_obj, obj else: source, destination = obj, rel_obj robj = factories.RelationshipFactory(source=source, destination=destination) resp = self.object_generator.api.delete(robj) self.assertStatus(resp, expected_code) @ddt.data( ("yes", "readonly system"), ("no", "non readonly system"), ) @ddt.unpack def test_readonly_searchable(self, test_value, expected_title): """Test filtration by readonly attribute""" with factories.single_commit(): factories.SystemFactory(title="readonly system", readonly=True) factories.SystemFactory(title="non readonly system") self.client.get("/login") actual_systems = self.simple_query( "System", expression=["readonly", "=", test_value]) self.assertEqual([s.get("title") for s in actual_systems], [expected_title])
class TestCreator(TestCase): """ TestCreator """ def setUp(self): super(TestCreator, self).setUp() self.api = Api() self.object_generator = ObjectGenerator() self.init_users() def init_users(self): """ Init users needed by the test cases """ users = [("creator", "Creator"), ("admin", "Administrator")] self.users = {} for (name, role) in users: _, user = self.object_generator.generate_person( data={"name": name}, user_role=role) self.users[name] = user def test_admin_page_access(self): """Permissions to admin page.""" for role, code in (("creator", 403), ("admin", 200)): self.api.set_user(self.users[role]) self.assertEqual(self.api.client.get("/admin").status_code, code) def test_creator_can_crud(self): """ Test Basic create/read,update/delete operations """ self.api.set_user(self.users["creator"]) creator_id = self.users["creator"].id audit_id = factories.AuditFactory().id all_errors = [] base_models = { "DataAsset", "Contract", "Requirement", "Policy", "Regulation", "Standard", "Document", "Facility", "Market", "Objective", "OrgGroup", "Vendor", "Product", "System", "Process", "Project", "AccessGroup", "Metric", "ProductGroup", "TechnologyEnvironment", } for model_singular in base_models: try: model = get_model(model_singular) table_singular = model._inflector.table_singular table_plural = model._inflector.table_plural # Test POST creation response, _ = self.object_generator.generate_object( model, data={ table_singular: { "title": model_singular, "context": None, "documents_reference_url": "ref", # ignored except for Document "link": "https://example.com", "contact": { "type": "Person", "id": creator_id }, # this is ignored on everything but Issues "audit": { "id": audit_id, "type": "Audit", } }, } ) if response.status_code != 201: all_errors.append("{} post creation failed {} {}".format( model_singular, response.status, response.data)) continue # Test GET when not owner obj_id = response.json.get(table_singular).get("id") response = self.api.get(model, obj_id) if response.status_code != 403: # we are not onwers yet all_errors.append( "{} can retrieve object if not owner".format(model_singular)) continue response = self.api.get_collection(model, obj_id) collection = response.json.get( "{}_collection".format(table_plural)).get(table_plural) if collection: all_errors.append( "{} can retrieve object if not owner (collection)" .format(model_singular)) continue # Test GET when owner acr = all_models.AccessControlRole.query.filter_by( object_type=model_singular, name="Admin" ).one() acl = all_models.AccessControlList.query.filter_by( object_id=obj_id, object_type=model_singular, ac_role=acr, ).one() factories.AccessControlPersonFactory( ac_list=acl, person_id=creator_id, ) response = self.api.get(model, obj_id) if response.status_code != 200: all_errors.append("{} can't GET object {}".format( model_singular, response.status)) continue # Test GET collection when owner response = self.api.get_collection(model, obj_id) collection = response.json.get( "{}_collection".format(table_plural)).get(table_plural) if not collection: all_errors.append( "{} cannot retrieve object even if owner (collection)" .format(model_singular)) continue except: all_errors.append("{} exception thrown".format(model_singular)) raise self.assertEqual(all_errors, []) def test_creator_search(self): """Test if creator can see the correct object while using the search api""" self.api.set_user(self.users['admin']) self.api.post(all_models.Regulation, { "regulation": {"title": "Admin regulation", "context": None}, }) self.api.set_user(self.users['creator']) acr_id = all_models.AccessControlRole.query.filter_by( object_type="Policy", name="Admin" ).first().id response = self.api.post(all_models.Policy, { "policy": { "title": "Creator Policy", "context": None, "access_control_list": [ acl_helper.get_acl_json(acr_id, self.users["creator"].id)], }, }) response.json.get("policy").get("id") response, _ = self.api.search("Regulation,Policy") entries = response.json["results"]["entries"] self.assertEqual(len(entries), 1) self.assertEqual(entries[0]["type"], "Policy") response, _ = self.api.search("Regulation,Policy", counts=True) self.assertEqual(response.json["results"]["counts"]["Policy"], 1) self.assertEqual( response.json["results"]["counts"].get("Regulation"), None) def _get_count(self, obj): """ Return the number of counts for the given object from search """ response, _ = self.api.search(obj, counts=True) return response.json["results"]["counts"].get(obj) def test_creator_should_see_users(self): """ Test if creator can see all the users in the system """ self.api.set_user(self.users['admin']) admin_count = self._get_count("Person") self.api.set_user(self.users['creator']) creator_count = self._get_count("Person") self.assertEqual(admin_count, creator_count) def test_relationships_access(self): """Check if creator cannot access relationship objects""" self.api.set_user(self.users['admin']) _, first_regulation = self.object_generator.generate_object( all_models.Regulation, data={"regulation": {"title": "Test regulation", "context": None}} ) _, second_regulation = self.object_generator.generate_object( all_models.Regulation, data={"regulation": {"title": "Test regulation 2", "context": None}} ) response, rel = self.object_generator.generate_relationship( first_regulation, second_regulation ) relationship_id = rel.id self.assertEqual(response.status_code, 201) self.api.set_user(self.users['creator']) response = self.api.get_collection(all_models.Relationship, relationship_id) self.assertEqual(response.status_code, 200) num = len(response.json["relationships_collection"]["relationships"]) self.assertEqual(num, 0) def test_revision_access(self): """Check if creator can access the right revision objects.""" def gen(title, extra_data=None): """Generates requirement.""" requirement_content = {"title": title, "context": None} if extra_data: requirement_content.update(**extra_data) return self.object_generator.generate_object( all_models.Requirement, data={"requirement": requirement_content} )[1] def check(obj, expected): """Check that how many revisions of an object current user can see.""" response = self.api.get_query( all_models.Revision, "resource_type={}&resource_id={}".format(obj.type, obj.id) ) self.assertEqual(response.status_code, 200) self.assertEqual( len(response.json['revisions_collection']['revisions']), expected ) self.api.set_user(self.users["admin"]) obj_1 = gen("Test Requirement 1") self.api.set_user(self.users["creator"]) acr_id = all_models.AccessControlRole.query.filter_by( object_type="Requirement", name="Admin" ).first().id linked_acl = { "access_control_list": [ acl_helper.get_acl_json(acr_id, self.users["creator"].id)], } check(obj_1, 0) obj_2 = gen("Test Requirement 2", linked_acl) obj2_acl = obj_2.access_control_list[0][1] check(obj_2, 1) check(obj2_acl, 1) @ddt.data("creator", "admin") def test_count_type_in_accordion(self, glob_role): """Return count of Persons in DB for side accordion.""" self.api.set_user(self.users[glob_role]) ocordion_api_person_count_link = ( "/search?" "q=&types=Program%2CWorkflow_All%2C" "Audit%2CAssessment%2CIssue%2CRegulation%2C" "Policy%2CStandard%2CContract%2CRequirement%2CControl%2C" "Objective%2CPerson%2COrgGroup%2CVendor%2CAccessGroup%2CSystem%2C" "Process%2CDataAsset%2CProduct%2CProject%2CFacility%2C" "Market%2CRisk%2CThreat&counts_only=true&" "extra_columns=Workflow_All%3DWorkflow%2C" "Workflow_Active%3DWorkflow%2CWorkflow_Draft%3D" "Workflow%2CWorkflow_Inactive%3DWorkflow&contact_id=1&" "extra_params=Workflow%3Astatus%3DActive%3BWorkflow_Active" "%3Astatus%3DActive%3BWorkflow_Inactive%3Astatus%3D" "Inactive%3BWorkflow_Draft%3Astatus%3DDraft" ) resp = self.api.client.get(ocordion_api_person_count_link) self.assertIn("Person", resp.json["results"]["counts"]) self.assertEqual(all_models.Person.query.count(), resp.json["results"]["counts"]["Person"]) @ddt.data( ("/api/revisions?resource_type={}&resource_id={}", 1), ("/api/revisions?source_type={}&source_id={}", 0), ("/api/revisions?destination_type={}&destination_id={}", 1), ) @ddt.unpack def test_changelog_access(self, link, revision_count): """Test accessing changelog under GC user who is assigned to object""" with factories.single_commit(): audit = factories.AuditFactory() asmnt = factories.AssessmentFactory(audit=audit) asmnt_id = asmnt.id factories.RelationshipFactory(source=audit, destination=asmnt) factories.AccessControlPersonFactory( ac_list=asmnt.acr_name_acl_map["Verifiers"], person=self.users["creator"], ) self.api.set_user(self.users["creator"]) response = self.api.client.get(link.format("Assessment", asmnt_id)) self.assert200(response) self.assertEqual( len(response.json.get("revisions_collection", {}).get("revisions")), revision_count ) @staticmethod def _query_revisions(api, resource_type, resource_id): """Helper function querying revisions related to particular object.""" return api.send_request( api.client.post, api_link="/query", data=[{ "object_name": "Revision", "type": "ids", "filters": { "expression": { "left": { "left": { "left": "resource_type", "op": {"name": "="}, "right": resource_type, }, "op": {"name": "AND"}, "right": { "left": "resource_id", "op": {"name": "="}, "right": resource_id, }, }, "op": {"name": "OR"}, "right": { "left": { "left": { "left": "source_type", "op": {"name": "="}, "right": resource_type, }, "op": {"name": "AND"}, "right": { "left": "source_id", "op": {"name": "="}, "right": resource_id, } }, "op": {"name": "OR"}, "right": { "left": { "left": "destination_type", "op": {"name": "="}, "right": resource_type, }, "op": {"name": "AND"}, "right": { "left": "destination_id", "op": {"name": "="}, "right": resource_id, } } } }, }, }], ) def test_revision_access_query(self): """Test GC assigned to obj can access revisions through query API.""" with factories.single_commit(): program = factories.ProgramFactory() audit = factories.AuditFactory() factories.RelationshipFactory( source=audit, destination=program, ) factories.AccessControlPersonFactory( ac_list=audit.acr_name_acl_map["Auditors"], person=self.users["creator"], ) audit_id = audit.id self.api.set_user(self.users["creator"]) response = self._query_revisions(self.api, audit.type, audit_id) self.assert200(response) self.assertEqual(response.json[0]["Revision"]["count"], 2) def test_rev_access_query_no_right(self): """Test GC has no access to revisions of objects it has no right on.""" with factories.single_commit(): program = factories.ProgramFactory() audit = factories.AuditFactory() factories.RelationshipFactory( source=audit, destination=program, ) audit_id = audit.id self.api.set_user(self.users["creator"]) response = self._query_revisions(self.api, audit.type, audit_id) self.assert200(response) self.assertEqual(response.json[0]["Revision"]["count"], 0)
class TestExternalRelationship(TestCase): """Integration test suite for External Relationship.""" # pylint: disable=invalid-name def setUp(self): """Init API helper""" super(TestExternalRelationship, self).setUp() self.object_generator = ObjectGenerator() self.api = api_helper.Api() with factories.single_commit(): editor_role = all_models.Role.query.filter( all_models.Role.name == "Editor").first() self.person_ext = factories.PersonFactory( email="*****@*****.**") self.person_ext_id = self.person_ext.id self.person = factories.PersonFactory( email="*****@*****.**") self.person_id = self.person.id rbac_factories.UserRoleFactory(role=editor_role, person=self.person) HEADERS = { "Content-Type": "application/json", "X-requested-by": "External App", "X-ggrc-user": "******"email\": \"[email protected]\"}", "X-appengine-inbound-appid": "test_external_app", } REL_URL = "/api/relationships" @staticmethod def build_relationship_json(source, destination, is_external=True): """Builds relationship create request json.""" return json.dumps([{ "relationship": { "source": { "id": source.id, "type": source.type }, "destination": { "id": destination.id, "type": destination.type }, "context": { "id": None }, "is_external": is_external } }]) @staticmethod def create_relationship(source, destination, is_external, user): """Creates relationship in database with given params.""" return factories.RelationshipFactory( source=source, destination=destination, is_external=is_external, modified_by_id=user.id, ) def test_create_ext_user_ext_relationship(self): """Validation external app user creates external relationship.""" self.api.set_user(self.person_ext) with factories.single_commit(): product = factories.ProductFactory() system = factories.SystemFactory() response = self.api.client.post(self.REL_URL, data=self.build_relationship_json( product, system, True), headers=self.HEADERS) self.assert200(response) relationship = all_models.Relationship.query.get( response.json[0][-1]["relationship"]["id"]) self.assertEqual(relationship.source_type, "Product") self.assertEqual(relationship.source_id, product.id) self.assertEqual(relationship.destination_type, "System") self.assertEqual(relationship.destination_id, system.id) self.assertTrue(relationship.is_external) self.assertEqual(relationship.modified_by_id, self.person_ext.id) self.assertIsNone(relationship.parent_id) self.assertIsNone(relationship.automapping_id) self.assertIsNone(relationship.context_id) def test_create_ext_user_reg_relationship(self): """Validation external app user creates regular relationship.""" self.api.set_user(self.person_ext) with factories.single_commit(): product = factories.ProductFactory() system = factories.SystemFactory() response = self.api.client.post(self.REL_URL, data=self.build_relationship_json( product, system, False), headers=self.HEADERS) self.assert400(response) self.assertEqual(response.json[0], [ 400, "You do not have the necessary permissions to " "create regular relationships.", ]) def test_update_ext_user_ext_relationship(self): """Validation external app user updates external relationship.""" self.api.set_user(self.person_ext) with factories.single_commit(): product = factories.ProductFactory() system = factories.SystemFactory() self.create_relationship(product, system, True, self.person_ext) response = self.api.client.post(self.REL_URL, data=self.build_relationship_json( product, system, True), headers=self.HEADERS) self.assert200(response) relationship = all_models.Relationship.query.get( response.json[0][-1]["relationship"]["id"]) self.assertEqual(relationship.source_type, "Product") self.assertEqual(relationship.source_id, product.id) self.assertEqual(relationship.destination_type, "System") self.assertEqual(relationship.destination_id, system.id) self.assertTrue(relationship.is_external) self.assertEqual(relationship.modified_by_id, self.person_ext.id) self.assertIsNone(relationship.parent_id) self.assertIsNone(relationship.automapping_id) self.assertIsNone(relationship.context_id) def test_update_ext_user_reg_relationship(self): """External app user can update regular relationship.""" with factories.single_commit(): product = factories.ProductFactory() system = factories.SystemFactory() self.create_relationship(product, system, False, self.person) product_id = product.id system_id = system.id self.api.set_user(self.person_ext) product = all_models.Product.query.get(product_id) system = all_models.System.query.get(system_id) response = self.api.client.post(self.REL_URL, data=self.build_relationship_json( product, system, True), headers=self.HEADERS) self.assert200(response) self.assertEqual(response.json[0][1]["relationship"]["is_external"], True) def test_delete_ext_user_ext_relationship(self): """Validation external app user deletes external relationship.""" self.api.set_user(self.person_ext) with factories.single_commit(): product = factories.ProductFactory() system = factories.SystemFactory() rel = self.create_relationship(product, system, True, self.person_ext) response = self.api.delete(rel) self.assert200(response) relationship = all_models.Relationship.query.get(rel.id) self.assertIsNone(relationship) def test_delete_ext_user_reg_relationship(self): """External app user can delete regular relationship.""" self.api.set_user(self.person_ext) with factories.single_commit(): product = factories.ProductFactory() system = factories.SystemFactory() rel = self.create_relationship(product, system, False, self.person_ext) response = self.api.delete(rel) self.assert200(response) def test_update_reg_user_ext_relationship(self): """Validation regular app user updates external relationship.""" with factories.single_commit(): product = factories.ProductFactory() system = factories.SystemFactory() self.create_relationship(product, system, True, self.person_ext) product_id = product.id system_id = system.id self.api.set_user(self.person) product = all_models.Product.query.get(product_id) system = all_models.System.query.get(system_id) response = self.api.client.post(self.REL_URL, data=self.build_relationship_json( product, system, False), headers=self.HEADERS) self.assert200(response) def test_delete_reg_user_ext_relationship(self): """Validation regular user deletes external relationship.""" with factories.single_commit(): product = factories.ProductFactory() system = factories.SystemFactory() self.create_relationship(product, system, True, self.person_ext) self.api.set_user(self.person) rel = all_models.Relationship.query.first() response = self.api.delete(rel) self.assert200(response) relationship = all_models.Relationship.query.get(rel.id) self.assertIsNone(relationship) @ddt.data(*READONLY_MAPPING_PAIRS) @ddt.unpack def test_local_delete_relationship_scoping_directive(self, model1, model2): """Test deletion of relationship between {0.__name__} and {1.__name__}""" # Set up relationships with self.object_generator.api.as_external(): _, obj1 = self.object_generator.generate_object(model1) _, obj2 = self.object_generator.generate_object(model2) _, rel = self.object_generator.generate_relationship( obj1, obj2, is_external=True) # check that relationship cannot be deleted by regular user self.api.set_user(all_models.Person.query.get(self.person_id)) relationship = all_models.Relationship.query.get(rel.id) response = self.api.delete(relationship) self.assert400(response) @ddt.data(*READONLY_MAPPING_PAIRS) @ddt.unpack def test_local_create_relationship_scoping_directive(self, model1, model2): """Test creation of relationship between {0.__name__} and {1.__name__}""" # Set up relationships with self.object_generator.api.as_external(): _, obj1 = self.object_generator.generate_object(model1) _, obj2 = self.object_generator.generate_object(model2) self.object_generator.api.set_user( all_models.Person.query.get(self.person_id)) response, _ = self.object_generator.generate_relationship( obj1, obj2, is_external=True) self.assert400(response) @ddt.data(*READONLY_MAPPING_PAIRS) @ddt.unpack def test_ext_create_delete_relationship_scoping_directive( self, model1, model2): """Test ext user and relationship between {0.__name__} and {1.__name__}""" # Set up relationships with self.object_generator.api.as_external(): _, obj1 = self.object_generator.generate_object(model1) _, obj2 = self.object_generator.generate_object(model2) _, rel = self.object_generator.generate_relationship( obj1, obj2, is_external=True) self.assertIsNotNone(rel) # check that external relationship can be deleted by external user self.api.set_user(all_models.Person.query.get(self.person_ext_id)) relationship = all_models.Relationship.query.get(rel.id) response = self.api.delete(relationship) print response.json self.assert200(response)
class TestWithReadOnlyAccessAPI(TestCase, query_helper.WithQueryApi): """Test WithReadOnlyAccess mixin""" def setUp(self): super(TestWithReadOnlyAccessAPI, self).setUp() self.object_generator = ObjectGenerator() self.object_generator.api.login_as_normal() @ddt.data( ('System', True), ('System', False), ('System', None), ('System', _NOT_SPECIFIED), ('System', "qwert"), ) @ddt.unpack def test_readonly_ignored_on_post(self, obj_type, readonly): """Test flag readonly ignored on object {0} POST for body readonly={1}""" dct = dict() if readonly is not _NOT_SPECIFIED: dct['readonly'] = readonly resp, obj = self.object_generator.generate_object( get_model(obj_type), dct, ) self.assertStatus(resp, 201) self.assertFalse(obj.readonly) @ddt.data( ('System', True, True), ('System', False, False), ('System', None, False), ('System', _NOT_SPECIFIED, False), ) @ddt.unpack def test_readonly_set_on_post_as_external(self, obj_type, readonly, result): """Test flag readonly on {0} POST for body readonly={1} as external user""" dct = dict() if readonly is not _NOT_SPECIFIED: dct['readonly'] = readonly with self.object_generator.api.as_external(): resp, obj = self.object_generator.generate_object( get_model(obj_type), dct, ) obj_id = obj.id self.assertStatus(resp, 201) obj = get_model(obj_type).query.get(obj_id) self.assertEqual(obj.readonly, result) @ddt.data( ('System', False, False, 200), ('System', False, True, 200), ('System', False, None, 200), ('System', False, _NOT_SPECIFIED, 200), ('System', False, "qwerty", 200), ('System', True, False, 405), ('System', True, True, 405), ('System', True, None, 405), ('System', True, _NOT_SPECIFIED, 405), ('System', True, "qwerty", 405), ) @ddt.unpack def test_put(self, obj_type, current, new, exp_code): """Test {0} PUT readonly={2} for current readonly={1}""" factory = factories.get_model_factory(obj_type) with factories.single_commit(): obj = factory(title='a', readonly=current) obj_id = obj.id data = {'title': 'b'} if new is not _NOT_SPECIFIED: data['readonly'] = new resp = self.object_generator.api.put(obj, data) self.assertStatus(resp, exp_code) obj = get_model(obj_type).query.get(obj_id) self.assertEqual(obj.readonly, current) @ddt.data( ('System', False, False, 200, False), ('System', False, True, 200, True), ('System', False, None, 200, False), ('System', False, _NOT_SPECIFIED, 200, False), ('System', True, False, 200, False), ('System', True, True, 200, True), ('System', True, None, 200, True), ('System', True, _NOT_SPECIFIED, 200, True), ) @ddt.unpack def test_put_as_external(self, obj_type, current, new, exp_code, exp_readonly): """Test {0} PUT readonly={2} for current readonly={1} for external user""" factory = factories.get_model_factory(obj_type) with factories.single_commit(): obj = factory(title='a', readonly=current) obj_id = obj.id data = {'title': 'b'} if new is not _NOT_SPECIFIED: data['readonly'] = new with self.object_generator.api.as_external(): obj = get_model(obj_type).query.get(obj_id) resp = self.object_generator.api.put(obj, data) self.assertStatus(resp, exp_code) obj = get_model(obj_type).query.get(obj_id) self.assertEqual(obj.readonly, exp_readonly) @ddt.data('System') def test_403_if_put_readonly_without_perms(self, obj_type): """Test {0} with readonly=True PUT returns 401 instead of 405 This test ensures that user without permission for the object cannot obtain value for flag readonly """ role_obj = all_models.Role.query.filter( all_models.Role.name == "Creator").one() factory = factories.get_model_factory(obj_type) with factories.single_commit(): # create Global Creator person = factories.PersonFactory() person_id = person.id rbac_factories.UserRoleFactory(role=role_obj, person=person) # Create object obj = factory(title='a', readonly=True) obj_id = obj.id self.object_generator.api.set_user(all_models.Person.query.get(person_id)) obj = get_model(obj_type).query.get(obj_id) resp = self.object_generator.api.put(obj, {'title': 'b'}) self.assert403(resp) @ddt.data( ('System', True, False, 200, True), ('System', True, True, 405, False), ('System', False, False, 200, True), ('System', False, True, 405, False), ) @ddt.unpack def test_delete(self, obj_type, is_external, readonly, exp_code, exp_deleted): """Test {0} DELETE if readonly={1}""" factory = factories.get_model_factory(obj_type) with factories.single_commit(): obj = factory(title='a', readonly=readonly) obj_id = obj.id if is_external: self.object_generator.api.login_as_external() else: self.object_generator.api.login_as_normal() obj = get_model(obj_type).query.get(obj_id) resp = self.object_generator.api.delete(obj) self.assertStatus(resp, exp_code) obj = get_model(obj_type).query.get(obj_id) if exp_deleted: self.assertIsNone(obj) else: self.assertIsNotNone(obj) @ddt.data('System') def test_403_if_delete_readonly_without_perms(self, obj_type): """Test {0} with readonly=True DELETE returns 401 This test ensures that user without permission for the object cannot obtain value for flag readonly """ role_obj = all_models.Role.query.filter( all_models.Role.name == "Creator").one() factory = factories.get_model_factory(obj_type) with factories.single_commit(): # create Global Creator person = factories.PersonFactory() person_id = person.id rbac_factories.UserRoleFactory(role=role_obj, person=person) # Create object obj = factory(title='a', readonly=True) obj_id = obj.id self.object_generator.api.set_user(all_models.Person.query.get(person_id)) obj = get_model(obj_type).query.get(obj_id) resp = self.object_generator.api.delete(obj) self.assert403(resp) obj = get_model(obj_type).query.get(obj_id) self.assertIsNotNone(obj) @ddt.data( ('System', False, 'Document', True, 201), ('System', False, 'Document', False, 201), ('System', True, 'Document', True, 405), ('System', True, 'Document', False, 405), ('System', False, 'Comment', True, 201), ('System', False, 'Comment', False, 201), ('System', True, 'Comment', True, 201), ('System', True, 'Comment', False, 201), ) @ddt.unpack def test_relationship_post(self, obj_type, readonly, rel_obj_type, swap, expected_code): """Test PUT relationship {0}.readonly={1}, related object type {2}""" factory = factories.get_model_factory(obj_type) rel_factory = factories.get_model_factory(rel_obj_type) with factories.single_commit(): obj = factory(title='a', readonly=readonly) rel_obj = rel_factory() if swap: source, destination = rel_obj, obj else: source, destination = obj, rel_obj resp, _ = self.object_generator.generate_relationship( source=source, destination=destination ) self.assertStatus(resp, expected_code) @ddt.data( ('System', False, 'Document', True, 200), ('System', False, 'Document', False, 200), ('System', True, 'Document', True, 405), ('System', True, 'Document', False, 405), ('System', False, 'Comment', True, 200), ('System', False, 'Comment', False, 200), ('System', True, 'Comment', True, 200), ('System', True, 'Comment', False, 200), ) @ddt.unpack def test_relationship_delete(self, obj_type, readonly, rel_obj_type, swap, expected_code): """Test DELETE relationship {0}.readonly={1}, related object type {2}""" factory = factories.get_model_factory(obj_type) rel_factory = factories.get_model_factory(rel_obj_type) with factories.single_commit(): obj = factory(title='a', readonly=readonly) rel_obj = rel_factory() if swap: source, destination = rel_obj, obj else: source, destination = obj, rel_obj robj = factories.RelationshipFactory(source=source, destination=destination) resp = self.object_generator.api.delete(robj) self.assertStatus(resp, expected_code) @ddt.data( ("yes", "readonly system"), ("no", "non readonly system"), ) @ddt.unpack def test_readonly_searchable(self, test_value, expected_title): """Test filtration by readonly attribute""" with factories.single_commit(): factories.SystemFactory(title="readonly system", readonly=True) factories.SystemFactory(title="non readonly system") self.client.get("/login") actual_systems = self.simple_query( "System", expression=["readonly", "=", test_value] ) self.assertEqual( [s.get("title") for s in actual_systems], [expected_title] )