def setUp(self): """Setup tests data""" super(TestIssueUnmap, self).setUp() self.generator = generator.ObjectGenerator(fail_no_json=False) with factories.single_commit(): audit = factories.AuditFactory() self.audit_id = audit.id assessments = [ factories.AssessmentFactory(audit=audit) for _ in range(2) ] objectives = [factories.ObjectiveFactory() for _ in range(2)] snapshots = self._create_snapshots(audit, objectives) self.snapshot_ids = [s.id for s in snapshots] issue = factories.IssueFactory() self.issue_id = issue.id factories.RelationshipFactory(source=audit, destination=assessments[0]) factories.RelationshipFactory(source=audit, destination=assessments[1]) factories.RelationshipFactory(source=assessments[0], destination=snapshots[0]) factories.RelationshipFactory(source=assessments[0], destination=snapshots[1]) factories.RelationshipFactory(source=assessments[1], destination=snapshots[1]) self.unmap_rel_id1 = factories.RelationshipFactory( source=issue, destination=assessments[0]).id self.unmap_rel_id2 = factories.RelationshipFactory( source=issue, destination=assessments[1]).id
def test_get_cad_default(self, cad_type, default_value): """Check default_value for cad via object and direct cad api.""" with factories.single_commit(): objective = factories.ObjectiveFactory() cad = factories.CustomAttributeDefinitionFactory( definition_type="objective", attribute_type=cad_type, ) cad_id = cad.id objective_id = objective.id objective_resp = self.generator.api.get(objective, objective_id) cad_resp = self.generator.api.get(cad, cad_id) self.assert200(cad_resp) self.assert200(objective_resp) self.assertIn("custom_attribute_definitions", objective_resp.json["objective"]) _cads = objective_resp.json["objective"][ "custom_attribute_definitions"] self.assertEqual(1, len(_cads)) cad_json = _cads[0] self.assertEqual(cad_id, cad_json["id"]) self.assertIn("default_value", cad_json) self.assertEqual(default_value, cad_json["default_value"]) self.assertIn("custom_attribute_definition", cad_resp.json) self.assertIn("default_value", cad_resp.json["custom_attribute_definition"]) self.assertEqual( default_value, cad_resp.json["custom_attribute_definition"]["default_value"])
def test_change_person_revision(self): """Test Control revision created if person is changed in import.""" user = all_models.Person.query.filter_by( email="*****@*****.**").first() with factories.single_commit(): control = factories.ControlFactory(modified_by=user) objective = factories.ObjectiveFactory() person = factories.PersonFactory() for role_name in ("Admin", "Control Operators", "Control Owners"): control.add_person_with_role(person, role_name) revisions = db.session.query(all_models.Revision.action).filter_by( resource_type=control.type, resource_id=control.id) self.assertEqual(revisions.all(), [("created", )]) response = self.import_data( collections.OrderedDict([ ("object_type", "Control"), ("Code*", control.slug), ("Control Operators", "*****@*****.**"), ("Control Owners", "*****@*****.**"), ("Map:Objective", objective.slug), ])) self._check_csv_response(response, {}) self.assertEqual(revisions.all(), [('created', ), ('modified', )])
def test_mapped_regulations_acl(self): """Test creation of acl roles for Regulations and Objective snapshots.""" with factories.single_commit(): person = factories.PersonFactory() person_email = person.email audit = factories.AuditFactory() assessment = factories.AssessmentFactory(audit=audit) for ac_role_id in self.assignee_roles.values(): assessment.add_person_with_role_id(person, ac_role_id) factories.RelationshipFactory(source=audit, destination=assessment) control = factories.ControlFactory() objective = factories.ObjectiveFactory() regulation = factories.RegulationFactory() snapshots = self._create_snapshots( audit, [control, objective, regulation]) factories.RelationshipFactory(source=snapshots[0], destination=snapshots[1]) factories.RelationshipFactory(source=snapshots[2], destination=snapshots[0]) factories.RelationshipFactory(source=assessment, destination=snapshots[0]) for role in ["Assignees", "Creators", "Verifiers"]: for snapshot in snapshots: # Mapped Assignee roles should be created for all snapshots, not only # for control that related to assessment self.assert_propagated_role(role, person_email, snapshot)
def setUp(self): super(TestIssueRelevantFilter, self).setUp() self.client.get("/login") self.snapshottable = factories.ObjectiveFactory() revision = all_models.Revision.query.filter_by( resource_id=self.snapshottable.id, resource_type=self.snapshottable.type, ).first() with factories.single_commit(): self.control = factories.ControlFactory() self.audit = factories.AuditFactory() self.issue = factories.IssueFactory() self.snapshot = factories.SnapshotFactory( parent=self.audit, child_id=self.snapshottable.id, child_type=self.snapshottable.type, revision_id=revision.id, ) factories.RelationshipFactory(source=self.issue, destination=self.control) factories.RelationshipFactory(source=self.issue, destination=self.audit) factories.RelationshipFactory(source=self.issue, destination=self.snapshot) self.objects = { "Issue": self.issue, "Control": self.control, "Snapshot": self.snapshot, "Snapshottable": self.snapshottable, }
def setUp(self): super(TestIssueAutomappings, self).setUp() # TODO: replace this hack with a special test util from ggrc.login import noop noop.login( ) # this is needed to pass the permission checks in automapper snapshottable = factories.ObjectiveFactory() with factories.single_commit(): self.audit, self.asmt, self.snapshot = self._make_audit_asmt_snapshot( snapshottable, ) self.issue = factories.IssueFactory() self.issue_audit = factories.IssueFactory() self.issue_snapshot = factories.IssueFactory() factories.RelationshipFactory(source=self.issue_audit, destination=self.audit) # to map an Issue to a Snapshot, you first should map it to Audit factories.RelationshipFactory(source=self.issue_snapshot, destination=self.audit) factories.RelationshipFactory(source=self.issue_snapshot, destination=self.snapshot)
def test_filter_by_checkbox_cad_no_cav(self): """Test index by Checkdoxed cad no cav.""" checkbox_type = all_models.CustomAttributeDefinition.ValidTypes.CHECKBOX cad_title = "Checkbox" search_value = "No" with factories.single_commit(): factories.CustomAttributeDefinitionFactory( attribute_type=checkbox_type, definition_type="objective", title=cad_title, ) objective = factories.ObjectiveFactory() revision = all_models.Revision.query.filter( all_models.Revision.resource_id == objective.id, all_models.Revision.resource_type == objective.type, ).first() revision.content = objective.log_json() db.session.add(revision) with factories.single_commit(): snapshot = factories.SnapshotFactory( child_id=objective.id, child_type=objective.type, revision=revision) db.session.expire_all() snapshot_id = snapshot.id self.client.post("/admin/full_reindex") snapshot = all_models.Snapshot.query.get(snapshot_id) self.assert_indexed_fields(snapshot, cad_title, {"": search_value})
def setUp(self): super(TestRevisionHistory, self).setUp() self.api = Api() roles = {r.name: r for r in all_models.Role.query.all()} with factories.single_commit(): factories.AccessControlRoleFactory( name="ACL_Reader", object_type="Control", update=0, ) factories.AccessControlRoleFactory(name="ACL_Editor", object_type="Control") with factories.single_commit(): self.control = factories.ControlFactory() self.objective = factories.ObjectiveFactory() self.program = factories.ProgramFactory() self.program.context.related_object = self.program self.relationship = factories.RelationshipFactory( source=self.program, destination=self.control, context=self.program.context, ) self.people = { "Creator": factories.PersonFactory(), "Reader": factories.PersonFactory(), "Editor": factories.PersonFactory(), "Administrator": factories.PersonFactory(), "ACL_Reader": factories.PersonFactory(), "ACL_Editor": factories.PersonFactory(), "Program Editors": factories.PersonFactory(), "Program Managers": factories.PersonFactory(), "Program Readers": factories.PersonFactory(), } for role_name in ["Creator", "Reader", "Editor", "Administrator"]: rbac_factories.UserRoleFactory(role=roles[role_name], person=self.people[role_name]) for role_name in [ "Program Editors", "Program Managers", "Program Readers" ]: person = self.people[role_name] rbac_factories.UserRoleFactory(role=roles["Creator"], person=person) factories.AccessControlPersonFactory( ac_list=self.program.acr_name_acl_map[role_name], person=self.people[role_name], ) with factories.single_commit(): for role_name in ["ACL_Reader", "ACL_Editor"]: rbac_factories.UserRoleFactory(role=roles["Creator"], person=self.people[role_name]) factories.AccessControlPersonFactory( ac_list=self.control.acr_name_acl_map[role_name], person=self.people[role_name], )
def test_audit_snapshot_editing(self, rolename, object_role, status, archived): """Test if {0}-{1} can edit objects in the audit context: {1}-snapshot""" with factories.single_commit(): audit = factories.AuditFactory(archived=archived) program = audit.program factories.RelationshipFactory(source=program, destination=audit) user = self.create_user_with_role(rolename) if object_role: program.add_person_with_role_name(user, object_role) objective = factories.ObjectiveFactory(title="objective") factories.RelationshipFactory(source=program, destination=objective) revision = all_models.Revision.query.filter( all_models.Revision.resource_type == 'Objective').first() rev_id = revision.id # Create snapshot objects: snapshot = factories.SnapshotFactory( child_id=revision.resource_id, child_type=revision.resource_type, parent=audit, revision=revision, context=audit.context, ) snapshot_id = snapshot.id factories.RelationshipFactory(source=audit, destination=snapshot) self.api.set_user(user) snapshot = all_models.Snapshot.query.get(snapshot_id) # update obj to create new revision self.api.put( all_models.Objective.query.get(snapshot.revision.resource_id), { "status": "Active", } ) json = { "update_revision": "latest" } response = self.api.put(snapshot, json) assert response.status_code == status, \ "{} put returned {} instead of {} for {}".format( rolename, response.status, status, 'snapshot') if status != 200: # if editing is allowed check if edit was correctly saved return assert response.json['snapshot'].get("revision_id", None) > rev_id, \ "snapshot has not been updated to the latest revision {}".format( response.json['snapshot'])
def test_audit_manual_snapshots(self): """Test audit with manual snapshot mapping""" with factories.single_commit(): program = factories.ProgramFactory() control = factories.ControlFactory() control_id = control.id control2 = factories.ControlFactory( ) # wouldn't be mapped to objective control2_id = control2.id objective = factories.ObjectiveFactory() factories.RelationshipFactory(source=program, destination=control) factories.RelationshipFactory(source=program, destination=control2) factories.RelationshipFactory(source=program, destination=objective) factories.RelationshipFactory(source=control, destination=objective) self.api.post(all_models.Audit, [{ "audit": { "title": "New Audit", "program": { "id": program.id, "type": program.type }, "status": "Planned", "context": None, "manual_snapshots": True, } }]) self.assertSnapshotCount(0) audit = all_models.Audit.query.first() control = all_models.Control.query.get(control_id) control2 = all_models.Control.query.get(control2_id) objective = all_models.Objective.query.first() self.gen.generate_relationship(audit, control) control_snapshot_id = all_models.Snapshot.query.filter_by( child_id=control_id, child_type="Control").first().id self.assertEqual(self.count_related_objectives(control_snapshot_id), 0) self.gen.generate_relationship(audit, objective) self.assertEqual(self.count_related_objectives(control_snapshot_id), 1) self.gen.generate_relationship(audit, control2) control2_snapshot_id = all_models.Snapshot.query.filter_by( child_id=control2_id, child_type="Control").first().id self.assertEqual(self.count_related_objectives(control2_snapshot_id), 0) self.assertSnapshotCount(3)
def test_ext_app_delete_normal_relationship(self): """External app can't delete normal relationships""" with factories.single_commit(): issue = factories.IssueFactory() objective = factories.ObjectiveFactory() relationship = factories.RelationshipFactory(source=issue, destination=objective, is_external=False) relationship_id = relationship.id ext_api = ExternalApiClient(use_ggrcq_service_account=True) resp = ext_api.delete("relationship", relationship_id) self.assertStatus(resp, 400)
def test_latest_revision_delete_cad(self, is_add_cav): """Test creating new revision after deleting CAD. In case of deleting CAD, snapshot attribute is_latest_revision must be False """ with factories.single_commit(): objective = factories.ObjectiveFactory() program = factories.ProgramFactory() factories.RelationshipFactory( source=program, destination=objective, ) audit = factories.AuditFactory() factories.RelationshipFactory(source=audit, destination=objective) cad = factories.CustomAttributeDefinitionFactory( title="test_name", definition_type="objective", attribute_type="Text", ) if is_add_cav: factories.CustomAttributeValueFactory( custom_attribute=cad, attributable=objective, attribute_value="test", ) last_revision = models.Revision.query.filter( models.Revision.resource_id == objective.id, models.Revision.resource_type == objective.type, ).order_by(models.Revision.id.desc()).first() snapshot = factories.SnapshotFactory( parent=audit, child_id=objective.id, child_type=objective.type, revision=last_revision, ) self.assertTrue(snapshot.is_latest_revision) self.api_helper.delete(cad) snapshot = models.Snapshot.query.filter().first() self.assertFalse(snapshot.is_latest_revision)
def test_sync_service_delete_normal_relationship(self): """Sync service can delete normal relationships via unmap endpoint""" with factories.single_commit(): issue = factories.IssueFactory() objective = factories.ObjectiveFactory() relationship = factories.RelationshipFactory(source=issue, destination=objective, is_external=False) relationship_id = relationship.id resp = self.ext_api.unmap(issue, objective) self.assert200(resp) rel = all_models.Relationship.query.get(relationship_id) self.assertIsNone(rel)
def test_one_revision_created(self): """Test no create revision and events from duplicated relationship""" with factories.single_commit(): source = factories.ProgramFactory() destination = factories.ObjectiveFactory() data = [{ "relationship": { "context": None, "destination": { "id": source.id, "type": "Program", "href": "/api/programs/{}".format(source.id) }, "source": { "id": destination.id, "type": "Objective", "href": "/api/objectives/{}".format(destination.id) } } }] response = self.api.client.post("/api/relationships", data=json.dumps(data), headers=self.headers) self.assert200(response) rel_id = all_models.Relationship.query.one().id revs_count = all_models.Revision.query.filter_by( source_type="Objective", destination_type="Program").count() events_count = all_models.Event.query.filter_by( resource_id=rel_id, resource_type="Relationship", ).count() self.assertEqual(revs_count, 1) self.assertEqual(events_count, 1) response = self.api.client.post("/api/relationships", data=json.dumps(data), headers=self.headers) self.assert200(response) new_revs_count = all_models.Revision.query.filter_by( source_type="Objective", destination_type="Program").count() events_count = all_models.Event.query.filter_by( resource_id=rel_id, resource_type="Relationship", ).count() self.assertEqual(new_revs_count, 1) self.assertEqual(events_count, 1)
def test_mapped_regulations_read(self): """Test if creators can CRUD mapped Regulations and Objective snapshots.""" self.api.set_user(self.people.get("Editor")) with factories.single_commit(): audit = factories.AuditFactory() assessment = factories.AssessmentFactory(audit=audit) factories.AccessControlPersonFactory( ac_list=assessment.acr_name_acl_map["Creators"], person=self.people.get("Editor"), ) factories.AccessControlPersonFactory( ac_list=assessment.acr_name_acl_map["Assignees"], person=self.people.get("Creator"), ) factories.RelationshipFactory(source=audit, destination=assessment) control = factories.ControlFactory() objective = factories.ObjectiveFactory() regulation = factories.RegulationFactory() snapshots = self._create_snapshots( audit, [control, objective, regulation]) for snapshot in snapshots: factories.RelationshipFactory(source=audit, destination=snapshot) factories.RelationshipFactory(source=snapshots[0], destination=snapshots[1]) factories.RelationshipFactory(source=snapshots[2], destination=snapshots[0]) factories.RelationshipFactory(source=assessment, destination=snapshots[0]) self.api.set_user(self.people.get("Creator")) for snapshot in snapshots: db.session.add(snapshot) response = self.api.get(type(snapshot), snapshot.id) self.assertEqual( response.status_code, 200, "Cannot GET mapped object. Received {}".format( response.status)) db.session.add(snapshot) response = self.api.delete(snapshot) self.assertEqual( response.status_code, 403, "Can DELETE mapped object. Received {}".format( response.status))
def test_permissions_not_flush_on_simple_put(self): """Test that permissions in memcache are cleaned after PUT request.""" with ggrc_factories.single_commit(): user = self.create_user_with_role("Creator") objective = ggrc_factories.ObjectiveFactory() objective_id = objective.id objective.add_person_with_role_name(user, "Admin") self.api.set_user(user) self.api.client.get("/permissions") perm_ids = self.memcache_client.get("permissions:list") self.assertEqual(perm_ids, {"permissions:{}".format(user.id)}) objective = all_models.Objective.query.get(objective_id) response = self.api.put(objective, {"title": "new title"}) self.assert200(response) perm_ids = self.memcache_client.get("permissions:list") self.assertIn("permissions:{}".format(user.id), perm_ids)
def test_permissions_flush_on_delete(self): """Test that permissions in memcache are cleaned after DELETE request.""" with factories.single_commit(): user = self.create_user_with_role("Creator") objective = factories.ObjectiveFactory() objective.add_person_with_role_name(user, "Admin") objective_id = objective.id self.api.set_user(user) self.api.client.get("/permissions") perm_ids = self.memcache_client.get("permissions:list") self.assertEqual(perm_ids, {"permissions:{}".format(user.id)}) objective = all_models.Objective.query.get(objective_id) response = self.api.delete(objective) self.assert200(response) perm_ids = self.memcache_client.get("permissions:list") self.assertEqual(perm_ids, set())
def test_revision_after_del_cad(self, is_add_cav): """Test creating new revision after deleting CAD. In case of deleting CAD, new revision must be created for object, which had this CAD. """ with factories.single_commit(): objective = factories.ObjectiveFactory() cad = factories.CustomAttributeDefinitionFactory( title="test_name", definition_type="objective", ) cad_id = cad.id if is_add_cav: factories.CustomAttributeValueFactory( custom_attribute=cad, attributable=objective, attribute_value="text", ) revision_id = ggrc.models.Revision.query.filter( ggrc.models.Revision.resource_id == objective.id, ggrc.models.Revision.resource_type == objective.type, ).order_by(ggrc.models.Revision.id.desc()).first().id with self.api_helper.as_external(): self.api_helper.delete(cad, cad_id) objective = ggrc.models.Objective.query.first() last_revision_id = ggrc.models.Revision.query.filter( ggrc.models.Revision.resource_id == objective.id, ggrc.models.Revision.resource_type == objective.type, ).order_by(ggrc.models.Revision.id.desc()).first().id self.assertGreater(last_revision_id, revision_id)
def setUp(self): super(TestLastAssessmentDate, self).setUp() self.api = Api() self.generator = generator.ObjectGenerator() self.client.get("/login") person = models.Person.query.first() admin_control = models.AccessControlRole.query.filter_by( name="Admin", object_type="Control").first() admin_objective = models.AccessControlRole.query.filter_by( name="Admin", object_type="Objective").first() with factories.single_commit(): controls = [ factories.ControlFactory(slug="Control_{}".format(i), title="Control_{}".format(i)) for i in range(5) ] objectives = [ factories.ObjectiveFactory(slug="Objective_{}".format(i), title="Objective_{}".format(i)) for i in range(2) ] for obj in itertools.chain(controls, objectives): acr = admin_control if obj.type == "Control" else admin_objective factories.AccessControlList(object=obj, person=person, ac_role=acr) audit_0 = factories.AuditFactory(title="Audit_0") audit_1 = factories.AuditFactory(title="Audit_1") audit_0_snapshots = self._create_snapshots( audit_0, controls[:2] + objectives[:1]) audit_1_snapshots = self._create_snapshots( audit_1, controls[1:4] + objectives) assessment_0 = factories.AssessmentFactory(title="Assessment_0", audit=audit_0) assessment_1 = factories.AssessmentFactory(title="Assessment_1", audit=audit_1) factories.RelationshipFactory(source=assessment_0, destination=audit_0) factories.RelationshipFactory(source=audit_1, destination=assessment_1) # Audit 0 assessment mappings: factories.RelationshipFactory( source=assessment_0, destination=audit_0_snapshots[1], # snapshot of control_1 ) factories.RelationshipFactory( source=assessment_0, destination=audit_0_snapshots[2], # snapshot of objective_0 ) # Audit 1 assessment mappings: factories.RelationshipFactory( source=audit_1_snapshots[0], # snapshot of control_1 destination=assessment_1, ) factories.RelationshipFactory( source=assessment_1, destination=audit_1_snapshots[1], # snapshot of control_2 ) factories.RelationshipFactory( source=assessment_1, destination=audit_1_snapshots[3], # snapshot of objective_0 ) factories.RelationshipFactory( source=audit_1_snapshots[4], # snapshot of objective_1 destination=assessment_1, )
def test_import_map_objectives(self): """Test import can't map assessments with objectives""" audit = factories.AuditFactory(slug='AUDIT-9999') audit_id = audit.id objectives = [ factories.ObjectiveFactory( title='obj_999{}'.format(i), slug='OBJECTIVE-999{}'.format(i) ) for i in range(10) ] for objective in objectives: factories.RelationshipFactory(source=audit.program, destination=objective) response = self._import_file( 'assessments_map_with_objectives_in_scope_of_program.csv', True ) row_errors = { 'Line 10: You can not map Objective to Assessment, because ' 'this Objective is not mapped to the related audit.', 'Line 11: You can not map Objective to Assessment, because ' 'this Objective is not mapped to the related audit.', 'Line 12: You can not map Objective to Assessment, because ' 'this Objective is not mapped to the related audit.', 'Line 3: You can not map Objective to Assessment, because ' 'this Objective is not mapped to the related audit.', 'Line 4: You can not map Objective to Assessment, because ' 'this Objective is not mapped to the related audit.', 'Line 5: You can not map Objective to Assessment, because ' 'this Objective is not mapped to the related audit.', 'Line 6: You can not map Objective to Assessment, because ' 'this Objective is not mapped to the related audit.', 'Line 7: You can not map Objective to Assessment, because ' 'this Objective is not mapped to the related audit.', 'Line 8: You can not map Objective to Assessment, because ' 'this Objective is not mapped to the related audit.', 'Line 9: You can not map Objective to Assessment, because ' 'this Objective is not mapped to the related audit.' } expected_messages = { 'Assessment': { 'created': 0, 'row_errors': row_errors } } assessments = db.session.query(all_models.Assessment).filter_by( audit_id=audit_id).all() self.assertEqual(len(assessments), 0) self._check_csv_response(response, expected_messages) # update the audit to the latest version self.api.put(all_models.Audit.query.get(audit_id), {'snapshots': {'operation': 'upsert'}} ) response = self._import_file('assessments_map_to_obj_snapshots.csv') expected_messages = { 'Assessment': { 'created': 10, 'row_errors': set() } } assessments = db.session.query(all_models.Assessment).filter_by( audit_id=audit_id).all() self.assertEqual(len(assessments), 10) self._check_csv_response(response, expected_messages)
def test_sort_by_similarity(self): """Check sorting by __similarity__ value with query API.""" # pylint: disable=too-many-locals with factories.single_commit(): program_1 = factories.ProgramFactory(title="Program 1") objective_1_program_1 = factories.ObjectiveFactory( title="Objective 1") objective_2_program_1 = factories.ObjectiveFactory( title="Objective 2") control_1_program_1 = factories.ControlFactory(title="Control 1") control_2_program_1 = factories.ControlFactory(title="Control 2") self.make_relationships( program_1, [ objective_1_program_1, objective_2_program_1, control_1_program_1, control_2_program_1 ], ) program_1 = models.Program.query.filter_by(title="Program 1").one() _, audit_1 = self.obj_gen.generate_object( models.Audit, { "title": "Audit 1", "program": { "id": program_1.id }, "status": "Planned", }) _, audit_2 = self.obj_gen.generate_object( models.Audit, { "title": "Audit 2", "program": { "id": program_1.id }, "status": "Planned", }) objective_1_program_1 = models.Objective.query.filter_by( title="Objective 1").one() objective_2_program_1 = models.Objective.query.filter_by( title="Objective 2").one() control_1_program_1 = models.Control.query.filter_by( title="Control 1").one() control_2_program_1 = models.Control.query.filter_by( title="Control 2").one() assessment_mappings = [ [ audit_1, objective_1_program_1, objective_2_program_1, control_1_program_1, control_2_program_1 ], [audit_1, control_1_program_1, control_2_program_1], [audit_1, objective_1_program_1, control_1_program_1], [ audit_2, objective_1_program_1, objective_2_program_1, control_1_program_1, control_2_program_1 ], [audit_2, objective_1_program_1, control_1_program_1], [audit_2, control_1_program_1, control_2_program_1], ] # All created Assessments has 'Control' type so result weights are # equal to count of controls in assessment objects related to current one weights = [ [1, 1, 2, 2, 2], [1, 1, 2, 2, 2], [1, 1, 1, 1, 1], [1, 1, 2, 2, 2], [1, 1, 1, 1, 1], [1, 1, 2, 2, 2], ] assessments = self.make_assessments(assessment_mappings) assessment_ids = [ass.id for ass in assessments] for aid, weight_defs in zip(assessment_ids, weights): similar_objects = models.Assessment.get_similar_objects_query( id_=aid, types=["Assessment"], ).all() sorted_similar = sorted(similar_objects, key=lambda x: x.weight) self.assertEqual(weight_defs, [x.weight for x in sorted_similar]) query = [{ "object_name": "Assessment", "type": "ids", "order_by": [{ "name": "__similarity__" }], "filters": { "expression": { "op": { "name": "similar" }, "object_name": "Assessment", "ids": [str(aid)], }, }, }] response = self.client.post( "/query", data=json.dumps(query), headers={"Content-Type": "application/json"}, ) # our sorted results are only unstably sorted. As such we verify that # weights match and not actual object ids obj_weight = {so.id: so.weight for so in similar_objects} response_ids = json.loads(response.data)[0]["Assessment"]["ids"] response_weights = [obj_weight[rid] for rid in response_ids] self.assertListEqual( response_weights, [obj.weight for obj in sorted_similar], )
def test_similar_partially_matching(self): """Basic check of similar objects manually and via Query API. We create three programs, map one them to the two objectives, create two audits and verify that we get the same result manually and via Query API. We also ensure that for only single matching objective we do not fetch that assessment is as related. """ # pylint: disable=too-many-locals with factories.single_commit(): program_1 = factories.ProgramFactory(title="Program 1") program_2 = factories.ProgramFactory(title="Program 2") program_3 = factories.ProgramFactory(title="Program 3") objective_1_program_1 = factories.ObjectiveFactory( title="Objective 1") objective_2_program_1 = factories.ObjectiveFactory( title="Objective 2") self.make_relationships( program_1, [ objective_1_program_1, objective_2_program_1, ], ) self.make_relationships( program_2, [ objective_1_program_1, objective_2_program_1, ], ) self.make_relationships( program_3, [ objective_1_program_1, ], ) program_1 = models.Program.query.filter_by(title="Program 1").one() program_2 = models.Program.query.filter_by(title="Program 2").one() program_3 = models.Program.query.filter_by(title="Program 3").one() objective_1_program_1 = models.Objective.query.filter_by( title="Objective 1").one() objective_2_program_1 = models.Objective.query.filter_by( title="Objective 2").one() _, audit_1 = self.obj_gen.generate_object( models.Audit, { "title": "Audit 1", "program": { "id": program_1.id }, "status": "Planned", }) _, audit_2 = self.obj_gen.generate_object( models.Audit, { "title": "Audit 2", "program": { "id": program_2.id }, "status": "Planned", }) _, audit_3 = self.obj_gen.generate_object( models.Audit, { "title": "Audit 3", "program": { "id": program_3.id }, "status": "Planned", }) assessment_mappings = [ [ audit_1, "Objective", objective_1_program_1, objective_2_program_1 ], [ audit_2, "Objective", objective_1_program_1, objective_2_program_1 ], [audit_3, "Objective"], ] assessments = self.make_assessments(assessment_mappings, with_types=True) similar_objects = models.Assessment.get_similar_objects_query( id_=assessments[0].id, types=["Assessment"], ).all() expected_ids = {assessments[1].id} self.assertSetEqual( {obj.id for obj in similar_objects}, expected_ids, ) self.assertNotIn(assessments[2].id, similar_objects) query = [{ "object_name": "Assessment", "type": "ids", "filters": { "expression": { "op": { "name": "similar" }, "object_name": "Assessment", "ids": [str(assessments[0].id)], }, }, }] response = self.client.post( "/query", data=json.dumps(query), headers={"Content-Type": "application/json"}, ) self.assertSetEqual( set(json.loads(response.data)[0]["Assessment"]["ids"]), expected_ids, )
def test_complex_propagation_count(self): """Test multiple object ACL propagation. This test is meant to catch invalid ACL entries for propagation that can not happen. Example for this is propagation control -> relationships -> document. In that propagation rule we should only propagate control acl entries to relationships to documents. But what can happen is; when a control has multiple relationships, some to objects and only one to document, all of those relationships would get an ACL entry even though in some cases that is a propagation dead end. Setup for this test is: Objects: control regulation objective program audit assessment, assessment_2 Relationships: control - regulation control - objective objective - regulations program - control, regulation, objective, audit audit - assessment, assessment_2, audit - control-snapshot, regulation-snapshot, objective-snapshot control_snapshot - regulation_snapshot control_snapshot - objective_snapshot objective_snapshot - regulations_snapshot document - regulation, objective, control evidence - assessment """ # pylint: disable=too-many-locals with factories.single_commit(): control = factories.ControlFactory() regulation = factories.RegulationFactory() objective = factories.ObjectiveFactory() normal_objects = [control, regulation, objective] for obj1, obj2 in itertools.combinations(normal_objects, 2): if control in (obj1, obj2): with mock.patch( 'ggrc.models.relationship.is_external_app_user', return_value=True): factories.RelationshipFactory(source=obj1, destination=obj2, is_external=True) else: factories.RelationshipFactory(source=obj1, destination=obj2) assessment = factories.AssessmentFactory() assessment_2 = factories.AssessmentFactory(audit=assessment.audit) factories.RelationshipFactory( source=assessment, destination=assessment.audit, ) factories.RelationshipFactory( source=assessment_2, destination=assessment.audit, ) factories.RelationshipFactory( source=assessment.audit, destination=assessment.audit.program, ) for obj in normal_objects: factories.RelationshipFactory( source=assessment.audit.program, destination=obj, ) snapshots = self._create_snapshots(assessment.audit, normal_objects) for snapshot in snapshots: factories.RelationshipFactory( source=assessment.audit, destination=snapshot, ) for obj1, obj2 in itertools.combinations(snapshots, 2): factories.RelationshipFactory(source=obj1, destination=obj2) for obj in normal_objects: document = factories.DocumentFactory() factories.RelationshipFactory(source=obj, destination=document) evidence = factories.EvidenceUrlFactory() factories.RelationshipFactory(source=evidence, destination=assessment) acl_entry = control._access_control_list[0] propagation._propagate([acl_entry.id], self.user_id) self.assertEqual( all_models.AccessControlList.query.filter( all_models.AccessControlList.parent_id.isnot(None)).count(), 2, # 1 for relationship to document and 1 for document. ) acl_entry = next( acl for acl in assessment.audit.program._access_control_list if acl.ac_role.name == "Program Editors") propagation._propagate([acl_entry.id], self.user_id) self.assertEqual( all_models.AccessControlList.query.filter( all_models.AccessControlList.parent_id.isnot(None)).count(), 2 + 2 + 4 + 6 + 2 + 6 + 6 # 2 previous entries for control # 2 for audit (relationship + audit propagation) # 4 for assessments (2 assessments and 2 relationships for them) # 6 for snapshots (3 snapshots with relationships) # 2 assessment document with relationships # 6 for normal objects # 6 for normal object documents )
def test_complex_propagation_count(self): """Test multiple object ACL propagation. This test is meant to catch invalid ACL entries for propagation that can not happen. Example for this is propagation control -> relationships -> document. In that propagation rule we should only propagate control acl entries to relationships to documents. But what can happen is; when a control has multiple relationships, some to objects and only one to document, all of those relationships would get an ACL entry even though in some cases that is a propagation dead end. Setup for this test is: Objects: control regulation objective program audit assessment, assessment_2 Relationships: control - regulation control - objective objective - regulations program - control, regulation, objective, audit audit - assessment, assessment_2, audit - control-snapshot, regulation-snapshot, objective-snapshot control_snapshot - regulation_snapshot control_snapshot - objective_snapshot objective_snapshot - regulations_snapshot document - regulation, objective, control evidence - assessment """ with factories.single_commit(): person = factories.PersonFactory() control = factories.ControlFactory() regulation = factories.RegulationFactory() objective = factories.ObjectiveFactory() normal_objects = [control, regulation, objective] for obj1, obj2 in itertools.combinations(normal_objects, 2): factories.RelationshipFactory(source=obj1, destination=obj2) assessment = factories.AssessmentFactory() assessment_2 = factories.AssessmentFactory(audit=assessment.audit) factories.RelationshipFactory( source=assessment, destination=assessment.audit, ) factories.RelationshipFactory( source=assessment_2, destination=assessment.audit, ) factories.RelationshipFactory( source=assessment.audit, destination=assessment.audit.program, ) for obj in normal_objects: factories.RelationshipFactory( source=assessment.audit.program, destination=obj, ) snapshots = self._create_snapshots(assessment.audit, normal_objects) for snapshot in snapshots: factories.RelationshipFactory( source=assessment.audit, destination=snapshot, ) for obj1, obj2 in itertools.combinations(snapshots, 2): factories.RelationshipFactory(source=obj1, destination=obj2) for obj in normal_objects: document = factories.DocumentFactory() factories.RelationshipFactory(source=obj, destination=document) evidence = factories.EvidenceUrlFactory() factories.RelationshipFactory(source=evidence, destination=assessment) acl_entry = factories.AccessControlListFactory( person=person, ac_role=self.roles["Control"]["Admin"], object=control, ) propagation._propagate([acl_entry.id]) self.assertEqual( all_models.AccessControlList.query.count(), 3, # 1 for control, 1 for relationship to document and 1 for document. ) acl_entry = factories.AccessControlListFactory( person=person, ac_role=self.roles["Program"]["Program Editors"], object=assessment.audit.program, ) propagation._propagate([acl_entry.id]) self.assertEqual( all_models.AccessControlList.query.count(), 3 + 1 + 2 + 4 + 6 + 2 + 6 + 6 # 3 previous entries for control # 1 original program ACL entry # 2 for audit (relationship + audit propagation) # 4 for assessments (2 assessments and 2 relationships for them) # 6 for snapshots (3 snapshots with relationships) # 2 assessment document with relationships # 6 for normal objects # 6 for normal object documents )
def test_snapshot_del_w_snapshot(self): """Test validation of deletion of snapshot mapped to another snapshot""" # pylint: disable=too-many-locals, too-many-statements # Prepare assessment with control and objective and raised issue rel = all_models.Relationship control = factories.ControlFactory() control_id = control.id revision_c = all_models.Revision.query.filter( all_models.Revision.resource_id == control.id, all_models.Revision.resource_type == control.__class__.__name__).order_by( all_models.Revision.id.desc()).first() objective = factories.ObjectiveFactory() objective_id = objective.id revision_o = all_models.Revision.query.filter( all_models.Revision.resource_id == objective.id, all_models.Revision.resource_type == objective.__class__.__name__).order_by( all_models.Revision.id.desc()).first() with factories.single_commit(): program = factories.ProgramFactory() audit = factories.AuditFactory(program=program) snapshot_c = factories.SnapshotFactory( parent=audit, child_id=control.id, child_type=control.__class__.__name__, revision_id=revision_c.id) snapshot_o = factories.SnapshotFactory( parent=audit, child_id=objective.id, child_type=objective.__class__.__name__, revision_id=revision_o.id) snapshot_c_id = snapshot_c.id factories.RelationshipFactory(source=program, destination=control) factories.RelationshipFactory(source=program, destination=audit) factories.RelationshipFactory(source=objective, destination=control) factories.RelationshipFactory(source=snapshot_c, destination=audit) factories.RelationshipFactory(source=snapshot_o, destination=audit) factories.RelationshipFactory(source=snapshot_c, destination=snapshot_o) # Check related_objects endpoint related_objects = self._get_related_objects(snapshot_c_id) self.assertEqual(len(related_objects), 2) self.assertEqual(len(related_objects["Audit"]), 1) self.assertEqual(len(related_objects["Snapshot"]), 1) # Check validation forbids deletion with linked Snapshot resp = self.api.delete(all_models.Snapshot, snapshot_c_id) self.assertEqual(resp.status_code, 409) # Unmap original control and objective control = all_models.Control.query.get(control_id) objective = all_models.Objective.query.get(objective_id) control_objective = rel.find_related(control, objective).id self.api.delete(rel, control_objective) # Check successful deletion of control snapshot resp = self.api.delete(all_models.Snapshot, snapshot_c_id) self.assertEqual(resp.status_code, 200) self.assertFalse(all_models.Snapshot.query.get(snapshot_c_id)) # Check that snapshot unmapped from all objects successfully self.check_no_relationship(snapshot_c_id)
def setUp(self): self.clear_data() super(TestWithLastAssessmentDate, self).setUp() self.generator = integration.ggrc.generator.ObjectGenerator() self.client.get("/login") self.api = Api() program = factories.ProgramFactory(title="Last Assessment Date") controls = [factories.ControlFactory() for _ in range(3)] self.control_ids = [c.id for c in controls] for control in controls: factories.RelationshipFactory(source=program, destination=control) objectives = [factories.ObjectiveFactory() for _ in range(3)] self.objective_ids = [c.id for c in objectives] for objective in objectives: factories.RelationshipFactory(source=program, destination=objective) self._create_audit(program=program, title="Last Assessment Date Audit") c_snapshots = (db.session.query(all_models.Snapshot) .filter_by(child_type="Control").all()) o_snapshots = (db.session.query(all_models.Snapshot) .filter_by(child_type="Objective").all()) c_id_to_snap_id = {s.child_id: s.id for s in c_snapshots} o_id_to_snap_id = {s.child_id: s.id for s in o_snapshots} assessments = [factories.AssessmentFactory() for _ in range(3)] self.assessment_ids = [a.id for a in assessments] # Mappings: # controls[0]: assessments[0], assessments[1], assessments[2], # controls[1]: assessments[1], assessments[2], # controls[2]: assessments[2] # objectives[0]: assessments[0], # objectives[1]: assessments[0], assessments[1], # objectives[2]: assessments[0], assessments[1], assessments[2], # the first Assessment is completed earlier than the second, the third # Assessment is not completed. self._create_relationships( (c_id_to_snap_id[self.control_ids[0]], assessments[0]), (c_id_to_snap_id[self.control_ids[0]], assessments[1]), (c_id_to_snap_id[self.control_ids[0]], assessments[2]), (c_id_to_snap_id[self.control_ids[1]], assessments[1]), (c_id_to_snap_id[self.control_ids[1]], assessments[2]), (c_id_to_snap_id[self.control_ids[2]], assessments[2]), (o_id_to_snap_id[self.objective_ids[2]], assessments[0]), (o_id_to_snap_id[self.objective_ids[2]], assessments[1]), (o_id_to_snap_id[self.objective_ids[2]], assessments[2]), (o_id_to_snap_id[self.objective_ids[1]], assessments[0]), (o_id_to_snap_id[self.objective_ids[1]], assessments[1]), (o_id_to_snap_id[self.objective_ids[0]], assessments[0]), ) self.finished_dates = [datetime.datetime(2017, 2, 20, 13, 40, 0), datetime.datetime(2017, 3, 30, 14, 55, 0)] with freezegun.freeze_time(self.finished_dates[0]): assessments[0].status = all_models.Assessment.FINAL_STATE db.session.add(assessments[0]) with freezegun.freeze_time(self.finished_dates[1]): assessments[1].status = all_models.Assessment.FINAL_STATE db.session.add(assessments[1]) db.session.commit() query = all_models.Revision.query.filter_by(resource_type="Assessment") revision_ids = [revision.id for revision in query] computed_attributes.compute_attributes(revision_ids)
def test_change_modified_by(self, is_add_cav): """Test checked correct changing of modified_by_id field. User 1 create objective, user 2 delete CAD. After the deleting CAD test checking that modified_by field contains user 2. """ with factories.single_commit(): objective = factories.ObjectiveFactory() cad = factories.CustomAttributeDefinitionFactory( title="test_cad", definition_type="objective", attribute_type="Text", ) control_id = objective.id if is_add_cav: factories.CustomAttributeValueFactory(custom_attribute=cad, attributable=objective, attribute_value="test") user = self.gen.generate_person(data={ "name": "test_admin", "email": "*****@*****.**" }, user_role="Administrator")[1] self.api_helper.set_user(user) self.client.get("/login") objective_revisions = ggrc.models.Revision.query.filter( ggrc.models.Revision.resource_id == control_id, ggrc.models.Revision.resource_type == "Objective", ).order_by(ggrc.models.Revision.id.desc()).all() ids_before_del = set(revision.id for revision in objective_revisions) cad = ggrc.models.CustomAttributeDefinition.query.filter_by( title="test_cad").first() resp_delete = self.api_helper.delete(cad) self.assert200(resp_delete) cad = ggrc.models.CustomAttributeDefinition.query.filter_by( title="test_cad").first() self.assertIsNone(cad) objective_revisions_after = ggrc.models.Revision.query.filter( ggrc.models.Revision.resource_id == control_id, ggrc.models.Revision.resource_type == "Objective", ).order_by(ggrc.models.Revision.id.desc()).all() ids_after_del = set(revision.id for revision in objective_revisions_after) difference_revision_id = ids_after_del.difference(ids_before_del) last_revision = ggrc.models.Revision.query.filter( ggrc.models.Revision.resource_id == control_id, ggrc.models.Revision.resource_type == "Objective", ).order_by(ggrc.models.Revision.id.desc()).first() self.assertSetEqual(difference_revision_id, {last_revision.id}) expected_id = ggrc.models.Person.query.filter_by( name="test_admin").first().id self.assertEquals(last_revision.content["modified_by_id"], expected_id) self.assertEquals(last_revision.content["modified_by"]["id"], expected_id)
def test_import_map_objectives(self): """Test import mapping of assessments with objectives, mapped to related audit. """ audit = factories.AuditFactory(slug='AUDIT-9999') audit_id = audit.id objectives = [ factories.ObjectiveFactory(title='obj_999{}'.format(i), slug='OBJECTIVE-999{}'.format(i)) for i in range(10) ] for objective in objectives: factories.RelationshipFactory(source=audit.program, destination=objective) assessments_data = [ collections.OrderedDict([ ("object_type", "Assessment"), ("Code*", ""), ("Audit*", "AUDIT-9999"), ("title", "ASSESSMENT-999{}".format(i)), ("Assignees", "*****@*****.**"), ("Creators", "*****@*****.**"), ("map:objective versions", "OBJECTIVE-999{}".format(i)), ]) for i in range(10) ] response = self.import_data(*assessments_data, dry_run=True) row_errors = { 'Line 10: You can not map Objective to Assessment, because ' 'this Objective is not mapped to the related audit.', 'Line 11: You can not map Objective to Assessment, because ' 'this Objective is not mapped to the related audit.', 'Line 12: You can not map Objective to Assessment, because ' 'this Objective is not mapped to the related audit.', 'Line 3: You can not map Objective to Assessment, because ' 'this Objective is not mapped to the related audit.', 'Line 4: You can not map Objective to Assessment, because ' 'this Objective is not mapped to the related audit.', 'Line 5: You can not map Objective to Assessment, because ' 'this Objective is not mapped to the related audit.', 'Line 6: You can not map Objective to Assessment, because ' 'this Objective is not mapped to the related audit.', 'Line 7: You can not map Objective to Assessment, because ' 'this Objective is not mapped to the related audit.', 'Line 8: You can not map Objective to Assessment, because ' 'this Objective is not mapped to the related audit.', 'Line 9: You can not map Objective to Assessment, because ' 'this Objective is not mapped to the related audit.' } expected_messages = { 'Assessment': { 'created': 0, 'row_errors': row_errors } } self._check_csv_response(response, expected_messages) # update the audit to the latest version self.api.put(all_models.Audit.query.get(audit_id), {'snapshots': { 'operation': 'upsert' }}) response = self.import_data(*assessments_data) expected_messages = { 'Assessment': { 'created': 10, 'row_errors': set() } } assessments = db.session.query( all_models.Assessment).filter_by(audit_id=audit_id).all() self.assertEqual(len(assessments), 10) self._check_csv_response(response, expected_messages)