def test_preconditions_failed_with_several_mandatory_urls(self): """No preconditions failed if URLs required by CAs are present""" ca1 = CustomAttributeMock(self.assessment, attribute_type="Dropdown", dropdown_parameters=("foo,url_required", "0,4"), value="url_required") ca2 = CustomAttributeMock(self.assessment, attribute_type="Dropdown", dropdown_parameters=("foo,url_required", "0,4"), value="url_required") # only one URL provided yet url = factories.EvidenceUrlFactory(title="Mandatory URL", ) factories.RelationshipFactory( source=self.assessment, destination=url, ) # the second URL url = factories.EvidenceUrlFactory(title="Second mandatory URL", ) factories.RelationshipFactory( source=self.assessment, destination=url, ) preconditions_failed = self.assessment.preconditions_failed self.assertFalse(preconditions_failed) self.assertFalse(ca1.value.preconditions_failed) self.assertFalse(ca2.value.preconditions_failed)
def test_wrong_remove_action_assessment(self): """Test wrong remove action on assessment.""" assessment = factories.AssessmentFactory() evidence_id = factories.EvidenceUrlFactory().id response = self.api.put(assessment, {"actions": {"remove_related": [{}]}}) self.assert400(response) response = self.api.put(assessment, {"actions": {"remove_related": [ { "id": evidence_id, } ]}}) self.assert400(response) response = self.api.put(assessment, {"actions": {"remove_related": [ { "type": "Evidence", } ]}}) self.assert400(response) response = self.api.put(assessment, {"actions": {"remove_related": [ { "id": None, "type": "Evidence", } ]}}) self.assert400(response)
def test_put_relationship_405(self): """Ensures that ability to modify relationships via PUT was removed""" with factories.single_commit(): assessment = factories.AssessmentFactory() assessment_id = assessment.id assessment_2 = factories.AssessmentFactory() evidence = factories.EvidenceUrlFactory() rel_id = factories.RelationshipFactory(source=assessment, destination=evidence).id relationship = all_models.Relationship.query.get(rel_id) response = self.api.put( relationship, { "relationship": { "source": { "id": assessment_2.id, "type": assessment_2.type }, "destination": { "id": evidence.id, "type": evidence.type }, } }) self.assert405(response) self.assertEqual(relationship.source_id, assessment_id)
def __init__(self, user_id, acr, parent=None): """Set up objects for Evidence permission tests. Args: user_id: Id of user under which all operations will be run. acr: Instance of ACR that should be assigned for tested user. parent: Model name in scope of which objects should be set up. """ self.setup_program_scope(user_id, acr) with factories.single_commit(): evidence = factories.EvidenceUrlFactory() if parent == "Audit": self.mapping_id = factories.RelationshipFactory( source=self.audit, destination=evidence).id elif parent == "Assessment": self.mapping_id = factories.RelationshipFactory( source=self.assessment, destination=evidence).id self.evidence_id = evidence.id self.parent = parent self.admin_acr_id = all_models.AccessControlRole.query.filter_by( name="Admin", object_type="Evidence", ).one().id self.user_id = user_id self.api = Api() self.objgen = generator.ObjectGenerator() self.objgen.api = self.api if user_id: user = all_models.Person.query.get(user_id) self.api.set_user(user)
def test_evidence_change_assmt(self): """Test notification updated data when evidence values is changed""" with factories.single_commit(): evidence_url = "test.com" evidence_file = "test_gdrive.file" evidence_1 = factories.EvidenceUrlFactory(link=evidence_url, title=evidence_url) evidence_2 = factories.EvidenceFileFactory(link=evidence_file, title=evidence_file) response = self.api.put( self.assessment, { "actions": { "add_related": [ { "id": evidence_1.id, "type": "Evidence", }, { "id": evidence_2.id, "type": "Evidence", }, ] } }) self.assert200(response) notifs, notif_data = common.get_daily_notifications() updated = notif_data["*****@*****.**"]["assessment_updated"] self.assertEqual(len(notifs), 1) self.assertEqual( updated[self.assessment.id]["updated_data"]["EVIDENCE URL"], (evidence_url, "")) self.assertEqual( updated[self.assessment.id]["updated_data"]["EVIDENCE FILE"], (evidence_file, ""))
def test_archived_evidence_from_audit_backward(self): """Test evidence archived with audit in evidence -> audit""" expected_evidence_ids = [] with factories.single_commit(): audit = factories.AuditFactory() evidence = factories.EvidenceUrlFactory() factories.RelationshipFactory(source=evidence, destination=audit) expected_evidence_ids.append(evidence.id) self._archive_audit_and_check_evidence(audit, expected_evidence_ids)
def setup_objects(self): """Sets up all the objects needed by the tests""" objects = self.objects # Program objects['program'] = program = factories.ProgramFactory( title="A Program") # Controls objects['controls'] = controls = [ factories.ControlFactory(title="My First Control"), factories.ControlFactory(title="My Second Control") ] # Audit objects['audit'] = audit = factories.AuditFactory( program=objects['program'], access_control_list=[{ "ac_role_id": self.audit_roles['Auditors'].id, "person": { "id": self.people['created_auditor'].id }, }, { "ac_role_id": self.audit_roles['Audit Captains'].id, "person": { "id": self.people['created_captain'].id }, }]) factories.RelationshipFactory(source=program, destination=audit) # Assessment template objects['assessment_template'] = factories.AssessmentTemplateFactory() # Assessment objects['assessment'] = factories.AssessmentFactory(audit=audit) # Snapshot objects['snapshots'] = self._create_snapshots(audit, controls) for snapshot in objects['snapshots']: factories.RelationshipFactory(source=audit, destination=snapshot) # Issues objects['issue'] = factories.IssueFactory( access_control_list=[{ "ac_role_id": self.issue_roles['Admin'].id, "person": { "id": self.people['issue_admin'].id }, }]) # Comments objects['comment'] = factories.CommentFactory() objects['issue_comment'] = factories.CommentFactory() # Documents objects['issue_document'] = factories.DocumentFactory() # Evidence objects['evidence'] = factories.EvidenceUrlFactory()
def test_evidence_relevant(self): """Return ids of evidence in scope of given audit Exclude attached to audit itself """ with factories.single_commit(): audit = factories.AuditFactory() audit_id = audit.id assessment1 = factories.AssessmentFactory(audit=audit) assessment2 = factories.AssessmentFactory(audit=audit) factories.AssessmentFactory(audit=audit) evidence1 = factories.EvidenceUrlFactory() evidence1_id = evidence1.id evidence2 = factories.EvidenceUrlFactory() evidence2_id = evidence2.id evidence3 = factories.EvidenceUrlFactory() evidence3_id = evidence3.id factories.RelationshipFactory(source=assessment1, destination=evidence1) factories.RelationshipFactory(source=assessment2, destination=evidence2) factories.RelationshipFactory(source=audit, destination=evidence3) ids = self._get_first_result_set( { "object_name": "Evidence", "type": "ids", "filters": { "expression": { "object_name": "Audit", "op": {"name": "related_evidence"}, "ids": [audit_id], } } }, "Evidence", "ids" ) self.assertEqual(2, len(ids)) self.assertIn(evidence1_id, ids) self.assertIn(evidence2_id, ids) self.assertNotIn(evidence3_id, ids)
def test_audit_unmapping(self): """Unmap Evidence from Audit -> evidence.DEPRECATED""" with factories.single_commit(): audit = factories.AuditFactory() evidence = factories.EvidenceUrlFactory() factories.RelationshipFactory(source=audit, destination=evidence) self.assertEquals(evidence.START_STATE, evidence.status) relationship = all_models.Relationship.query.filter( all_models.Relationship.destination_id == evidence.id, all_models.Relationship.source_id == audit.id).one() self.api_helper.delete(relationship) evidence = self.refresh_object(evidence) self.assertEquals(evidence.DEPRECATED, evidence.status)
def test_unmap_evidence_as_src_assessment(self): """Test unmapping of evidence set as relationship source on assessment.""" assessment = factories.AssessmentFactory() evidence = factories.EvidenceUrlFactory() rel_id = factories.RelationshipFactory(destination=assessment, source=evidence).id response = self.api.put(assessment, {"actions": {"remove_related": [ { "id": evidence.id, "type": "Evidence", } ]}}) self.assert200(response) relationship = all_models.Relationship.query.get(rel_id) self.assertIsNone(relationship)
def test_map_evidence_assessment(self): """Test map evidence action on assessment.""" assessment = factories.AssessmentFactory() evidence = factories.EvidenceUrlFactory() response = self.api.put(assessment, {"actions": {"add_related": [ { "id": evidence.id, "type": "Evidence", } ]}}) self.assert200(response) relationship = _get_relationship( "Assessment", response.json["assessment"]["id"]) self.assertEqual(relationship.destination_id, evidence.id) self.assertEqual(relationship.source_id, assessment.id)
def map(self, evidence=None): """Map Evidence to parent object.""" if self.parent == "Audit": parent = all_models.Audit.query.get(self.audit_id) else: parent = all_models.Assessment.query.get(self.assessment_id) map_evidence = evidence if evidence else factories.EvidenceUrlFactory() return self.api.put( parent, { "actions": { "add_related": [{ "id": map_evidence.id, "type": "Evidence", }] } })
def test_preconditions_failed_with_present_mandatory_url(self): """No preconditions failed if url required by CA is present.""" ca = CustomAttributeMock( self.assessment, attribute_type="Dropdown", dropdown_parameters=("foo,url_required", "0,4"), value="url_required", ) url = factories.EvidenceUrlFactory(title="Mandatory url", ) factories.RelationshipFactory( source=self.assessment, destination=url, ) preconditions_failed = self.assessment.preconditions_failed self.assertFalse(preconditions_failed) self.assertFalse(ca.value.preconditions_failed)
def test_assessment_unmapping(self): """Unmap Evidence from Assessment -> evidence.DEPRECATED""" with factories.single_commit(): assessment = factories.AssessmentFactory() evidence = factories.EvidenceUrlFactory( parent_obj={ 'id': assessment.id, 'type': 'Assessment' } ) self.assertEquals(evidence.START_STATE, evidence.status) relationship = all_models.Relationship.query.filter( all_models.Relationship.destination_id == evidence.id, all_models.Relationship.source_id == assessment.id ).one() self.api_helper.delete(relationship) evidence = self.refresh_object(evidence) self.assertEquals(evidence.DEPRECATED, evidence.status)
def test_evidence_mapped_roles(self): """Test creation of mapped evidence roles.""" 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) evidence = factories.EvidenceUrlFactory() factories.RelationshipFactory(source=assessment, destination=evidence) db.session.add(evidence) for role in ["Assignees", "Creators", "Verifiers"]: self.assert_propagated_role(role, person_email, evidence)
def test_import_assessment_with_evidence_url_existing(self): """If url already mapped to assessment ignore it""" evidence_url = "test_gdrive_url" with factories.single_commit(): audit = factories.AuditFactory() assessment = factories.AssessmentFactory() assessment_slug = assessment.slug factories.RelationshipFactory(source=audit, destination=assessment) evidence = factories.EvidenceUrlFactory(link=evidence_url) factories.RelationshipFactory(source=assessment, destination=evidence) response = self.import_data(OrderedDict([ ("object_type", "Assessment"), ("Code*", assessment_slug), ("Evidence Url", evidence_url), ])) evidences = all_models.Evidence.query.filter_by(link=evidence_url).all() self.assertEquals(1, len(evidences)) self.assertEquals([], response[0]['row_warnings'])
def setUp(self): super(TestPermissionsOnAssessmentRelatedAssignables, self).setUp() self.api = Api() self.generator = ObjectGenerator() _, self.reader = self.generator.generate_person(user_role="Reader") audit = factories.AuditFactory() assessment = factories.AssessmentFactory(audit=audit) factories.AccessControlPersonFactory( ac_list=assessment.acr_name_acl_map["Assignees"], person=self.reader, ) factories.RelationshipFactory(source=audit, destination=assessment) evidence = factories.EvidenceUrlFactory() evidence_id = evidence.id evid_rel = factories.RelationshipFactory(source=assessment, destination=evidence) evid_rel_id = evid_rel.id self.api.set_user(self.reader) self.evidence = all_models.Evidence.query.get(evidence_id) self.evid_relationship = all_models.Relationship.query.get(evid_rel_id)
def setUp(self): super(TestPermissionsOnAssessmentRelatedAssignables, self).setUp() self.api = Api() self.generator = ObjectGenerator() _, self.reader = self.generator.generate_person(user_role="Reader") audit = factories.AuditFactory() assessment = factories.AssessmentFactory(audit=audit) ac_role = all_models.AccessControlRole.query.filter_by( object_type=assessment.type, name="Assignees").first() factories.AccessControlListFactory(ac_role=ac_role, object=assessment, person=self.reader) factories.RelationshipFactory(source=audit, destination=assessment) evidence = factories.EvidenceUrlFactory() evidence_id = evidence.id evid_rel = factories.RelationshipFactory(source=assessment, destination=evidence) evid_rel_id = evid_rel.id self.api.set_user(self.reader) self.evidence = all_models.Evidence.query.get(evidence_id) self.evid_relationship = all_models.Relationship.query.get(evid_rel_id)
class TestFullFilledModelExport(TestCase): """Test for export a full filled model""" # pylint: disable=undefined-variable FIELDS_FILLED_RULES = { 'archived': lambda **kwargs: set_attribute( kwargs['obj'], 'archived', False ), 'assertions': lambda **kwargs: set_attribute( kwargs['obj'], 'assertions', 'assertions' ), 'assessment_template': lambda **kwargs: set_attribute( kwargs['obj'], 'assessment_template', 'assessment_template' ), 'assessment_type': lambda **kwargs: set_attribute( kwargs['obj'], 'assessment_type', 'Control' ), 'audit': lambda **kwargs: TestFullFilledModelExport._map_object( source=kwargs['obj'], destination=kwargs['obj'].audit ), 'categories': lambda **kwargs: set_attribute( kwargs['obj'], 'categories', '["categories"]' ), 'comments': lambda **kwargs: TestFullFilledModelExport._map_object( source=kwargs['obj'], destination=factories.CommentFactory( description='description', assignee_type='Admin' ) ), 'company': lambda **kwargs: set_attribute( kwargs['obj'], 'company', 'company' ), 'component_id': lambda **kwargs: factories.IssueTrackerIssueFactory( enabled=True, issue_tracked_obj=kwargs['obj'], issue_id=123, issue_type="PROCESS", component_id=12345, hotlist_id=12345, issue_priority="P2", issue_severity="S2", issue_url="somelink", ), 'contact': lambda **kwargs: set_attribute( kwargs['obj'], 'contact', kwargs['user'] ), 'created_at': lambda **kwargs: set_attribute( kwargs['obj'], 'created_at', datetime.date(2019, 9, 24) ), 'created_by': lambda **kwargs: set_attribute( kwargs['obj'], 'created_by_id', kwargs['user'].id ), 'cycle': lambda **kwargs: set_attribute( kwargs['obj'], 'cycle', 'cycle' ), 'cycle_task_group': lambda **kwargs: set_attribute( kwargs['obj'], 'cycle_task_group', 'cycle_task_group' ), 'cycle_workflow': lambda **kwargs: set_attribute( kwargs['obj'], 'cycle_workflow', 'cycle_workflow' ), 'default_assignees': lambda **kwargs: set_attribute( kwargs['obj'], 'default_assignees', kwargs['user'] ), 'default_verifier': lambda **kwargs: set_attribute( kwargs['obj'], 'default_verifier', kwargs['user'] ), 'directive': lambda **kwargs: set_attribute( kwargs['obj'], 'directive', 'directive' ), 'delete': lambda **kwargs: set_attribute( kwargs['obj'], 'delete', 'delete' ), 'description': lambda **kwargs: set_attribute( kwargs['obj'], 'description', 'description' ), 'design': lambda **kwargs: set_attribute( kwargs['obj'], 'design', 'Effective' ), 'documents_file': lambda **kwargs: TestFullFilledModelExport._map_object( source=factories.DocumentFileFactory(link='link'), destination=kwargs['obj'], ), 'documents_reference_url': lambda **kwargs: TestFullFilledModelExport._map_object( source=factories.DocumentReferenceUrlFactory(link='link'), destination=kwargs['obj'], ), 'due_date': lambda **kwargs: set_attribute( kwargs['obj'], 'due_date', datetime.date(2019, 9, 24) ), 'email': lambda **kwargs: set_attribute( kwargs['obj'], 'email', '*****@*****.**' ), 'enabled': lambda **kwargs: set_attribute( kwargs['obj'], 'enabled', True ), 'end_date': lambda **kwargs: set_attribute( kwargs['obj'], 'end_date', datetime.date(2019, 9, 24) ), 'evidences_file': lambda **kwargs: TestFullFilledModelExport._map_object( source=factories.EvidenceFileFactory(), destination=kwargs['obj'], ), 'evidences_url': lambda **kwargs: TestFullFilledModelExport._map_object( source=factories.EvidenceUrlFactory(), destination=kwargs['obj'], ), 'finished_date': lambda **kwargs: set_attribute( kwargs['obj'], 'finished_date', datetime.date(2019, 9, 24) ), 'folder': lambda **kwargs: set_attribute( kwargs['obj'], 'folder', 'folder' ), 'fraud_related': lambda **kwargs: set_attribute( kwargs['obj'], 'fraud_related', True ), 'hotlist_id': lambda **kwargs: set_attribute( kwargs['obj'], 'hotlist_id', 'hotlist_id' ), 'is_verification_needed': lambda **kwargs: set_attribute( kwargs['obj'], 'is_verification_needed', True ), 'issue_priority': lambda **kwargs: set_attribute( kwargs['obj'], 'issue_priority', 'issue_priority' ), 'issue_severity': lambda **kwargs: set_attribute( kwargs['obj'], 'issue_severity', 'issue_severity' ), 'issue_title': lambda **kwargs: set_attribute( kwargs['obj'], 'issue_title', 'issue_title' ), 'issue_tracker': lambda **kwargs: set_attribute( kwargs['obj'], 'issue_tracker', 'issue_tracker' ), 'issue_type': lambda **kwargs: set_attribute( kwargs['obj'], 'issue_type', 'issue_type' ), 'key_control': lambda **kwargs: set_attribute( kwargs['obj'], 'key_control', True ), 'kind': lambda **kwargs: set_attribute( kwargs['obj'], 'kind', all_models.Option.query.filter( all_models.Option == 'product_type' ).first() ), 'labels': lambda **kwargs: factories.ObjectLabelFactory( labeled_object=kwargs['obj'], label=factories.LabelFactory( object_type=kwargs['obj'].__tablename__ ), ), 'last_assessment_date': lambda **kwargs: TestFullFilledModelExport._create_attributes( kwargs['obj'], 1 ), 'last_comment': lambda **kwargs: TestFullFilledModelExport._create_attributes( kwargs['obj'], 3 ), 'last_deprecated_date': lambda **kwargs: set_attribute( kwargs['obj'], 'last_deprecated_date', datetime.date(2019, 9, 24) ), 'last_submitted_at': lambda **kwargs: set_attribute( kwargs['obj'], 'last_submitted_at', datetime.date(2019, 9, 24) ), 'last_submitted_by': lambda **kwargs: set_attribute( kwargs['obj'], 'last_submitted_by_id', kwargs['user'].id ), 'last_verified_at': lambda **kwargs: set_attribute( kwargs['obj'], 'last_verified_at', datetime.date(2019, 9, 24) ), 'last_verified_by': lambda **kwargs: set_attribute( kwargs['obj'], 'last_verified_by_id', kwargs['user'].id ), 'means': lambda **kwargs: set_attribute(kwargs['obj'], 'means', 'means'), 'modified_by': lambda **kwargs: set_attribute( kwargs['obj'], 'modified_by', kwargs['user'] ), 'name': lambda **kwargs: set_attribute(kwargs['obj'], 'name', 'name'), 'network_zone': lambda **kwargs: set_attribute( kwargs['obj'], 'network_zone', all_models.Option.query.filter( all_models.Option == 'network_zone' ).first() ), 'notes': lambda **kwargs: set_attribute(kwargs['obj'], 'notes', 'notes'), 'notify_custom_message': lambda **kwargs: set_attribute( kwargs['obj'], 'notify_custom_message', 'notify_custom_message' ), 'notify_on_change': lambda **kwargs: set_attribute( kwargs['obj'], 'notify_on_change', True ), 'operationally': lambda **kwargs: set_attribute( kwargs['obj'], 'operationally', 'Effective' ), 'people_sync_enabled': lambda **kwargs: set_attribute( kwargs['obj'], 'people_sync_enabled', True ), 'procedure_description': lambda **kwargs: set_attribute( kwargs['obj'], 'procedure_description', 'procedure description' ), 'program': lambda **kwargs: set_attribute( kwargs['obj'], 'program', 'program' ), 'readonly': lambda **kwargs: set_attribute( kwargs['obj'], 'readonly', True ), 'recipients': lambda **kwargs: set_attribute( kwargs['obj'], 'recipients', 'recipients' ), 'repeat_every': lambda **kwargs: set_attribute( kwargs['obj'], 'repeat_every', 1 ), 'report_end_date': lambda **kwargs: set_attribute( kwargs['obj'], 'report_end_date', datetime.date(2019, 9, 24)), 'report_start_date': lambda **kwargs: set_attribute( kwargs['obj'], 'report_start_date', datetime.date(2019, 8, 20) ), 'review_status': lambda **kwargs: set_attribute( kwargs['obj'], 'review_status', 'review status' ), 'review_status_display_name': lambda **kwargs: set_attribute( kwargs['obj'], 'review_status_display_name', 'review status display name' ), 'reviewers': lambda **kwargs: TestFullFilledModelExport._create_acl( 'Reviewers', factories.ReviewFactory(reviewable=kwargs['obj']), kwargs['user'], ), 'risk_type': lambda **kwargs: set_attribute( kwargs['obj'], 'risk_type', 'risk_type' ), 'secondary_contact': lambda **kwargs: set_attribute( kwargs['obj'], 'secondary_contact', kwargs['user'] ), 'send_by_default': lambda **kwargs: set_attribute( kwargs['obj'], 'send_by_default', True ), 'slug': lambda **kwargs: set_attribute(kwargs['obj'], 'slug', 'slug'), 'sox_302_enabled': lambda **kwargs: set_attribute( kwargs['obj'], 'sox_302_enabled', True ), 'start_date': lambda **kwargs: set_attribute( kwargs['obj'], 'start_date', datetime.date(2019, 8, 20) ), 'status': lambda **kwargs: set_attribute( kwargs['obj'], 'status', 'In Progress' ), 'task_group': lambda **kwargs: set_attribute( kwargs['obj'], 'task_group', 'task_group' ), 'task_type': lambda **kwargs: set_attribute( kwargs['obj'], 'task_type', 'text' ), 'template_custom_attributes': lambda **kwargs: set_attribute( kwargs['obj'], 'template_custom_attributes', 'adsasd' ), 'template_object_type': lambda **kwargs: set_attribute( kwargs['obj'], 'template_object_type', 'Objective' ), 'test_plan': lambda **kwargs: set_attribute( kwargs['obj'], 'test_plan', 'test_plan' ), 'test_plan_procedure': lambda **kwargs: set_attribute( kwargs['obj'], 'test_plan_procedure', True ), 'threat_event': lambda **kwargs: set_attribute( kwargs['obj'], 'threat_event', 'threat event' ), 'threat_source': lambda **kwargs: set_attribute( kwargs['obj'], 'threat_source', 'threat source' ), 'title': lambda **kwargs: set_attribute(kwargs['obj'], 'title', 'title'), 'unit': lambda **kwargs: set_attribute( kwargs['obj'], 'unit', all_models.Workflow.DAY_UNIT ), 'updated_at': lambda **kwargs: set_attribute( kwargs['obj'], 'updated_at', datetime.date(2019, 8, 20) ), 'user_role': lambda **kwargs: set_attribute( kwargs['obj'], 'user_role', 'user_role' ), 'verified_date': lambda **kwargs: set_attribute( kwargs['obj'], 'verified_date', datetime.date(2019, 9, 24) ), 'verify_frequency': lambda **kwargs: set_attribute( kwargs['obj'], 'verify_frequency', 'verify frequency' ), 'vulnerability': lambda **kwargs: set_attribute( kwargs['obj'], 'vulnerability', 'vulnerability' ), 'workflow': lambda **kwargs: set_attribute( kwargs['obj'], 'workflow', 'workflow' ), } @staticmethod def _create_attributes(obj, attribute_template_id): """Create attribute for object""" attr = all_models.Attributes( object_id=obj.id, object_type=obj.__class__.__name__, value_datetime=datetime.datetime(2019, 9, 26), value_string="last comment", attribute_template_id=attribute_template_id, updated_at=datetime.datetime.now(), created_at=datetime.datetime.now(), ) db.session.add(attr) db.session.commit() @staticmethod def _map_object(source, destination): """Create relationship with between two objects""" from ggrc.models import exceptions try: factories.RelationshipFactory(source=source, destination=destination) except exceptions.ValidationError: return def _map_snapshot(self, obj, destination): """Create relationship between object and his snapshot""" revision = self._get_latest_object_revisions([obj])[0] parent = destination if not isinstance(parent, all_models.Audit): parent = destination.audit snapshot = factories.SnapshotFactory( child_id=revision.resource_id, child_type=revision.resource_type, revision=revision, parent=parent, parent_id=parent.id, ) factories.RelationshipFactory(source=snapshot, destination=destination) @staticmethod def _create_acl(role, obj, user): """Propagate acl for obj""" ac_role = all_models.AccessControlRole.query.filter( all_models.AccessControlRole.name == role, all_models.AccessControlRole.object_type == obj.__class__.__name__, ).one() factories.AccessControlPersonFactory( ac_list=obj.acr_acl_map[ac_role], person=user, ) @staticmethod def _set_field(alias, obj, user): """Set field for model""" kwargs = {'obj': obj, 'user': user} set_attr = TestFullFilledModelExport.FIELDS_FILLED_RULES[alias] set_attr(**kwargs) @staticmethod def _get_aliases(model): """Get aliases for provided model""" return [c for c in import_helper.get_object_column_definitions(model)] def assert_full_filled_model(self, data): """Assert that all columns are filled for export Args: data: list of rows from csv table Raises: AssertionError: if not all require columns are filled for model """ errors = [] # these columns only for import ignore = ['Delete', 'Comments', 'Policy / Regulation / Standard / Contract', 'Template', 'Custom Attributes'] rows = csv.reader(StringIO(data)) rows = [r for r in rows][:3] for top, column_name, field_value in zip(*rows): if column_name.startswith('unmap:') or column_name in ignore: continue elif top == 'Object type': title = column_name continue if field_value == '': errors.append(column_name) self.assertEqual(errors, [], 'These columns for {0} are not exported: {1}'.format( title, ', '.join(errors))) def build_object(self, model): """Fill all fields in model""" errors = [] obj = factories.get_model_factory(model.__name__)() aliases = sorted(self._get_aliases(model)) for alias in aliases: if alias.startswith('__mapping__'): title = alias.split(':')[1] mapped_model = ''.join([part.title() for part in title.split()]) destination_obj = factories.get_model_factory(mapped_model)() self._map_object(source=obj, destination=destination_obj) elif alias.startswith('__snapshot_mapping__'): title = alias.split(':')[1] mapped_model = ''.join([part.title() for part in title.split()]) destination_obj = factories.get_model_factory(mapped_model)() self._map_snapshot(destination_obj, obj) elif alias.startswith('__acl__'): role = alias.split(':')[1] self._create_acl(role, obj, self.user) elif not alias.startswith('__'): try: self._set_field(alias, obj, self.user) except KeyError: errors.append(alias) else: continue db.session.commit() self.assertEqual(errors, [], 'These columns are not filled for model: {}. ' 'Need to add rule for these into ' 'FIELDS_FILLED_RULES'.format( ', '.join(errors))) return obj def setUp(self): super(TestFullFilledModelExport, self).setUp() self.api = api_helper.Api() self.client.get('/login') self.user = all_models.Person.query.filter( all_models.Person.email == "*****@*****.**" ).one() @ddt.data( *get_exportables() ) def test_full_filled_model_export(self, model): """Test export of {0.__name__} with all filled columns We defined dict with fillable fields from all models. So since we get some new column in model we need define it in `attrs_dict` Raises: AssertionError: 1. Raised when column isn't present in `attrs_dict`. So we need to add rules for this column to dict. 2. Raised when some columns are missed for export. So we need fix rules for columns in `attrs_dict`. """ model_name = model.__name__ obj = self.build_object(model) data = [{ "object_name": model_name, "filters": { "expression": { 'left': 'id', 'op': {'name': '='}, 'right': obj.id, } }, "fields": "all", }] response = self.export_csv(data) response_data = response.data self.assert_full_filled_model(response_data) self.assert200(response)
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_multiply_actions(self): """Test multiply actions""" assessment = factories.AssessmentFactory() evid_map = factories.EvidenceUrlFactory(link="google1.com") evid_del = factories.EvidenceUrlFactory(link="google2.com") factories.RelationshipFactory(source=assessment, destination=evid_del) ca_def = factories.CustomAttributeDefinitionFactory( title="def1", definition_type="assessment", definition_id=assessment.id, attribute_type="Dropdown", multi_choice_options="no,yes", multi_choice_mandatory="0,3" ) ca_val = factories.CustomAttributeValueFactory( custom_attribute=ca_def, attributable=assessment, attribute_value="no" ) response = self.api.put(assessment, { "custom_attribute_values": [ { "id": ca_val.id, "custom_attribute_id": ca_def.id, "attribute_value": "yes", "type": "CustomAttributeValue", }], "actions": {"add_related": [ { "id": None, "type": "Evidence", "kind": "FILE", "title": "evidence1", "link": "google3.com", "source_gdrive_id": "source_gdrive_id", }, { "id": evid_map.id, "type": "Evidence", }, { "id": None, "type": "Comment", "description": "comment1", "custom_attribute_definition_id": ca_def.id, } ], "remove_related": [ { "id": evid_del.id, "type": "Evidence", }]}}) self.assert200(response) preconditions_failed = response.json["assessment"]["preconditions_failed"] self.assertIs(preconditions_failed, True) assessment_by_url = self.simple_query( "Assessment", expression=["evidence url", "~", "google1.com"] ) self.assertEqual(len(assessment_by_url), 1) assessment_by_url = self.simple_query( "Assessment", expression=["evidence url", "~", "google2.com"] ) self.assertFalse(assessment_by_url) assessment_by_evidence = self.simple_query( "Assessment", expression=["evidence file", "~", "google3.com"] ) self.assertEqual(len(assessment_by_evidence), 1) assessment_by_comment = self.simple_query( "Assessment", expression=["comment", "~", "comment1"] ) self.assertEqual(len(assessment_by_comment), 1)