def test_acl_definitions(self, model): """Test ACL column definitions.""" with factories.single_commit(): factory = factories.AccessControlRoleFactory factories.AccessControlRoleFactory(object_type="Control", read=True) role_names = { factory(object_type=model.__name__).name for _ in range(2) } expected_names = set() if issubclass(model, roleable.Roleable): expected_names = role_names definitions = get_object_column_definitions(model) definition_names = {d["display_name"]: d for d in definitions.values()} self.assertLessEqual(expected_names, set(definition_names.keys()))
def test_get_mandatory_acrs(self, mandatory): """ACR and mandatory meta info if mandatory flag is {0}.""" control_id = self.control.id acr = factories.AccessControlRoleFactory(name="test_name", object_type=self.control.type, mandatory=mandatory) acr_id = acr.id resp = self.api.client.get( "/api/revisions" "?resource_type=Control&resource_id={}".format(control_id) ) collection = resp.json["revisions_collection"]["revisions"] self.assertTrue(collection) self.assertIn("meta", collection[0]) self.assertIn("mandatory", collection[0]["meta"]) self.assertIn("access_control_roles", collection[0]["meta"]["mandatory"]) mandatory_acrs = collection[0]["meta"]["mandatory"]["access_control_roles"] self.assertEqual(mandatory, acr_id in mandatory_acrs)
def test_acl_filter(self, test_role_name): """Control Snapshots are filtered and sorted by ACL Role.""" with factories.single_commit(): program = factories.ProgramFactory() person1 = factories.PersonFactory(name="Ann", email="*****@*****.**") control1 = factories.ControlFactory() control2 = factories.ControlFactory() program_id = program.id control1_id = control1.id control2_id = control2.id factories.RelationshipFactory(source=program, destination=control1) factories.RelationshipFactory(source=program, destination=control2) factories.AccessControlListFactory( ac_role=factories.AccessControlRoleFactory( name=test_role_name, object_type="Control"), person=person1, object_id=control1_id, object_type="Control", ) revision = all_models.Revision.query.filter( all_models.Revision.resource_type == "Control", all_models.Revision.resource_id == control1_id).order_by( all_models.Revision.updated_at.desc()).first() revision.content = control1.log_json() db.session.add(revision) db.session.commit() program = models.Program.query.filter_by(id=program_id).one() self._create_audit(program=program, title="some title") control_user1_result = self._get_first_result_set( self._make_snapshot_query_dict( "Control", expression=['{}'.format(test_role_name), "=", "Ann"]), "Snapshot", ) self.assertEqual(control_user1_result["count"], 1) snaps_dict = dict( all_models.Snapshot.query.filter( all_models.Snapshot.child_type == "Control").values( "child_id", "id")) self.assertIn(snaps_dict[control1_id], [i["id"] for i in control_user1_result["values"]]) self.assertNotIn(snaps_dict[control2_id], [i["id"] for i in control_user1_result["values"]])
def test_proposal_apply_review_status(self, notification_type, num_notifications_expected): """Change via proposal with ignorable attrs review status not change""" with factories.single_commit(): risk = factories.RiskFactory() review = factories.ReviewFactory( status=all_models.Review.STATES.REVIEWED, reviewable=risk, notification_type=notification_type) review_id = review.id user = factories.PersonFactory() acl = factories.AccessControlListFactory( ac_role=factories.AccessControlRoleFactory(object_type="Risk"), object=risk) proposal_content = { "access_control_list": { acl.ac_role_id: { "added": [{ "id": user.id, "email": user.email }], "deleted": [] } } } proposal = factories.ProposalFactory(instance=risk, content=proposal_content, agenda="agenda content") self.api.modify_object(proposal, {"status": proposal.STATES.APPLIED}) review = all_models.Review.query.get(review_id) self.assertEqual(review.status, all_models.Review.STATES.REVIEWED) review_notif_types = all_models.Review.NotificationObjectTypes notif_unreviewed_type = all_models.Notification.query.join( all_models.NotificationType).filter( all_models.NotificationType.name == review_notif_types.STATUS_UNREVIEWED).all() self.assertEqual(num_notifications_expected, len(notif_unreviewed_type))
def test_export_deleted_acr(self): """Test exporting snapshots with ACL entries for deleted ACRs.""" # pylint: disable=too-many-locals with factories.single_commit(): # Create one more custom role ac_role = factories.AccessControlRoleFactory( object_type="Control", name="Custom Role", ) control = factories.ControlFactory(slug="Control 1") person = factories.PersonFactory() factories.AccessControlListFactory( ac_role=ac_role, person=person, object=control, ) audit = factories.AuditFactory() # pylint: disable=protected-access # This is used to update control revision data with the new ACL entry # without making a put request to that control. factories.ModelFactory._log_event(control) self._create_snapshots(audit, [control]) db.session.delete(ac_role) db.session.commit() search_request = [{ "object_name": "Snapshot", "filters": { "expression": { "left": "child_type", "op": { "name": "=" }, "right": "Control", }, }, }] parsed_data = self.export_parsed_csv( search_request)["Control Snapshot"][0] self.assertNotIn("Custom Role", parsed_data)
def test_single_acl_entry(self): """Test ACL column import with single email.""" role = factories.AccessControlRoleFactory(object_type="Market") role_id = role.id response = self.import_data( OrderedDict([ ("object_type", "Market"), ("code", "market-1"), ("title", "Title"), ("Admin", "*****@*****.**"), (role.name, "*****@*****.**"), ])) self._check_csv_response(response, {}) market = models.Market.query.first() self.assertEqual(len(market.access_control_list), 1) self.assertEqual(market.access_control_list[0].ac_role_id, role_id) self.assertEqual(market.access_control_list[0].person.email, "*****@*****.**")
def test_proposal_delete_acl(self): """Test simple delete acl proposal.""" with factories.single_commit(): control = factories.ControlFactory(title="1") role = factories.AccessControlRoleFactory(name="role") person = factories.PersonFactory() factories.AccessControlListFactory( person=person, ac_role=role, object=control, ) with factories.single_commit(): latest_revision = all_models.Revision.query.filter( all_models.Revision.resource_id == control.id, all_models.Revision.resource_type == control.type).order_by( all_models.Revision.created_at.desc()).first() latest_revision.content = control.log_json() control_id = control.id role_id = unicode(role.id) person_id = person.id control_content = control.log_json() control_content["access_control_list"] = [] self.create_proposal(control, full_instance_content=control_content, agenda="delete access control roles", context=None) control = all_models.Control.query.get(control_id) self.assertEqual(1, len(control.proposals)) self.assertIn("access_control_list", control.proposals[0].content) acl = control.proposals[0].content["access_control_list"] self.assertIn(role_id, acl) role = control.proposals[0].content["access_control_list"][role_id] person = all_models.Person.query.get(person_id) self.assertEqual( { "added": [], "deleted": [{ "id": person_id, "email": person.email }], }, role) self.assertEqual(1, len(control.comments))
def test_acl_multiple_entries(self): """Test ACL column import with multiple emails.""" role = factories.AccessControlRoleFactory(object_type="Market") emails = {factories.PersonFactory().email for _ in range(3)} response = self.import_data( OrderedDict([ ("object_type", "Market"), ("code", "market-1"), ("title", "Title"), ("Admin", "*****@*****.**"), (role.name, "\n".join(emails)), ])) self._check_csv_response(response, {}) market = models.Market.query.first() self.assertEqual( {acl.person.email for acl in market.access_control_list}, emails, )
def test_admin_has_access(self): """Ensure that global creator has access to created proposal by him""" role_creator = all_models.Role.query.filter( all_models.Role.name == "Creator").one() # prepare - create program, assign roles factories.AccessControlRoleFactory(name="ACL_Reader", update=0, object_type="Program") with factories.single_commit(): program = factories.ProgramFactory() person = factories.PersonFactory() rbac_factories.UserRoleFactory(role=role_creator, person=person) factories.AccessControlPersonFactory( ac_list=program.acr_name_acl_map["ACL_Reader"], person=person, ) program_id = program.id # make query to create proposal self.api.set_user(person) self.client.get("/login") acr_class = all_models.AccessControlRole acr = acr_class.query.filter( acr_class.name == 'ProposalEditor', acr_class.object_type == 'Proposal').one() create_data = self._get_create_proposal_request( program_id, acr.id, person.id) self.api.post(all_models.Proposal, create_data) query_data = _get_query_proposal_request(program_id) headers = { "Content-Type": "application/json", } resp = self.api.client.post("/query", data=json.dumps(query_data), headers=headers).json self.assertEqual(1, len(resp)) self.assertEqual(resp[0]["Proposal"]["count"], 1)
def test_import_control_duplicate_slugs(self): """Test import does not fail when two objects with the same slug are imported.""" with factories.single_commit(): role_name = factories.AccessControlRoleFactory( object_type="Control").name emails = [factories.PersonFactory().email for _ in range(2)] control = factories.ControlFactory() self.import_data( collections.OrderedDict([ ("object_type", "Control"), ("code", control.slug), ("title", "Title"), ("Admin", "*****@*****.**"), (role_name, "\n".join(emails)), ])) import_dicts = [ collections.OrderedDict([ ("object_type", "Control"), ("code", control.slug), ("title", "Title"), ("Admin", "*****@*****.**"), (role_name, "\n".join(emails)), ]), collections.OrderedDict([ ("object_type", "Control"), ("code", control.slug), ("title", "Title"), ("Admin", "*****@*****.**"), (role_name, "\n".join(emails)), ]), ] response = self.import_data(*import_dicts) fail_response = { u'message': u'Import failed due to server error.', u'code': 400 } self.assertNotEqual(response, fail_response)
def test_proposal_for_acl(self): """Test simple add acl proposal.""" with factories.single_commit(): control = factories.ControlFactory(title="1") role = factories.AccessControlRoleFactory(name="role") person = factories.PersonFactory() control_id = control.id role_id = unicode(role.id) person_id = person.id control_content = control.log_json() control_content["access_control_list"] = [ {"ac_role_id": role_id, "person": {"type": "Person", "id": person.id}} ] resp = self.api.post( all_models.Proposal, {"proposal": { "instance": { "id": control.id, "type": control.type, }, # "content": {"123": 123}, "full_instance_content": control_content, "agenda": "update access control roles", "context": None, }}) self.assertEqual(201, resp.status_code) control = all_models.Control.query.get(control_id) self.assertEqual(1, len(control.proposals)) self.assertIn("access_control_list", control.proposals[0].content) acl = control.proposals[0].content["access_control_list"] self.assertIn(role_id, acl) role = control.proposals[0].content["access_control_list"][role_id] person = all_models.Person.query.get(person_id) self.assertEqual( { "added": [{"id": person_id, "email": person.email}], "deleted": [], }, role) self.assertEqual(1, len(control.comments))
def test_proposal_for_acl(self): """Test simple add acl proposal.""" with factories.single_commit(): control = factories.ControlFactory(title="1") role = factories.AccessControlRoleFactory(name="role", object_type=control.type, internal=False) person = factories.PersonFactory() control_id = control.id role_id = unicode(role.id) person_id = person.id control_content = control.log_json() control_content["access_control_list"] = [{ "ac_role_id": role_id, "person": { "type": "Person", "id": person.id } }] self.create_proposal(control, full_instance_content=control_content, agenda="update access control roles", context=None) control = all_models.Control.query.get(control_id) self.assertEqual(1, len(control.proposals)) self.assertIn("access_control_list", control.proposals[0].content) acl = control.proposals[0].content["access_control_list"] self.assertIn(role_id, acl) role = control.proposals[0].content["access_control_list"][role_id] person = all_models.Person.query.get(person_id) self.assertEqual( { "added": [{ "id": person_id, "email": person.email }], "deleted": [], }, role) self.assertEqual(1, len(control.comments))
def test_autogenerated_no_acl_in_snapshot(self, field, role_name): """Test autogenerated assessment assignees base on template settings and no ACL list in snapshot.""" email = "{}@example.com".format(field) with factories.single_commit(): person = factories.PersonFactory(email=email, name=field) factories.AccessControlRoleFactory( name=role_name, object_type=self.snapshot.child_type, ) template = factories.AssessmentTemplateFactory( test_plan_procedure=False, procedure_description="Assessment Template Test Plan", default_people={"assessors": role_name}) content = self.control.log_json() content.pop("access_control_list") content[field] = {"id": person.id} self.snapshot.revision.content = content db.session.add(self.snapshot.revision) response = self.assessment_post(template) self.assert_assignees("Assessor", response, email)
def test_multiple_acl_roles_update(self, first_roles, edited_roles): """Test updating objects via import with multiple ACL roles.""" with factories.single_commit(): for email in self._random_emails: factories.PersonFactory(email=email) for role_name in first_roles.keys(): factories.AccessControlRoleFactory( object_type="Market", name=role_name, ) import_dict = self._generate_role_import_dict(first_roles) self.import_data(import_dict) market = models.Market.query.first() stored_roles = {} for role_name in first_roles.keys(): stored_roles[role_name] = { acl.person.email for acl in market.access_control_list if acl.ac_role.name == role_name } self.assertEqual(stored_roles, first_roles) import_dict = self._generate_role_import_dict(edited_roles) self.import_data(import_dict) market = models.Market.query.first() stored_roles = {} for role_name in edited_roles.keys(): stored_roles[role_name] = { acl.person.email for acl in market.access_control_list if acl.ac_role.name == role_name } self.assertEqual(stored_roles, edited_roles)
def test_index_deleted_acr(self): """Test index by removed ACR.""" role_name = "Test name" with factories.single_commit(): acr = factories.AccessControlRoleFactory( name=role_name, object_type="Control" ) person = factories.PersonFactory(email="*****@*****.**", name='test') control = factories.ControlFactory() factories.AccessControlListFactory( ac_role=acr, person=person, object=control ) revision = all_models.Revision.query.filter( all_models.Revision.resource_id == control.id, all_models.Revision.resource_type == control.type, ).one() revision.content = control.log_json() db.session.add(revision) with factories.single_commit(): snapshot = factories.SnapshotFactory( child_id=control.id, child_type=control.type, revision=revision) db.session.expire_all() db.session.delete(acr) db.session.commit() snapshot_id = snapshot.id self.client.post("/admin/full_reindex") snapshot = all_models.Snapshot.query.get(snapshot_id) all_found_records = dict(Record.query.filter( Record.key == snapshot.id, Record.type == snapshot.type, Record.property == role_name.lower() ).values("subproperty", "content")) self.assertFalse(all_found_records)
def test_duplicated_acr_import(self): """Test import of LCAD with same name as GCAD.""" acr_name = "Test ACR" with factories.single_commit(): factories.AccessControlRoleFactory( object_type="Assessment", name=acr_name, ) audit = factories.AuditFactory() response = self.import_data(OrderedDict([ ("object_type", "Assessment_Template"), ("Code*", ""), ("Audit*", audit.slug), ("Default Assignees", "*****@*****.**"), ("Default Verifiers", "*****@*****.**"), ("Title", "Title"), ("Object Under Assessment", "Control"), ("Custom Attributes", "Text, {}".format(acr_name)), ])) expected_messages = { "Assessment Template": { "rows": 1, "updated": 0, "created": 0, "row_warnings": set(), "row_errors": { errors.ERROR_TEMPLATE.format( line=3, message=common_errors.DUPLICATE_CUSTOM_ROLE.format( role_name=acr_name ), ) }, } } self._check_csv_response(response, expected_messages)
def test_single_acl_entry(self): """Test ACL column import with single email.""" role = factories.AccessControlRoleFactory(object_type="Market") role_id = role.id response = self.import_data( OrderedDict([ ("object_type", "Market"), ("code", "market-1"), ("title", "Title"), ("Admin", "*****@*****.**"), ("Assignee", "*****@*****.**"), ("Verifier", "*****@*****.**"), (role.name, "*****@*****.**"), ])) self._check_csv_response(response, {}) market = models.Market.query.first() acl = models.AccessControlList.query.filter_by(ac_role_id=role_id, object_id=market.id, object_type="Market") self.assertEqual(acl.count(), 1) self.assertEqual(acl.first().ac_role_id, role_id) self.assertEqual(acl.first().person.email, "*****@*****.**")
def test_index_by_acr(self): """Test index by ACR.""" role_name = "Test name" with factories.single_commit(): acr = factories.AccessControlRoleFactory( name=role_name, object_type="Control" ) person = factories.PersonFactory(email="*****@*****.**", name='test') control = factories.ControlFactory() factories.AccessControlListFactory( ac_role=acr, person=person, object=control ) revision = all_models.Revision.query.filter( all_models.Revision.resource_id == control.id, all_models.Revision.resource_type == control.type, ).one() revision.content = control.log_json() db.session.add(revision) with factories.single_commit(): snapshot = factories.SnapshotFactory( child_id=control.id, child_type=control.type, revision=revision) db.session.expire_all() person_id = person.id snapshot_id = snapshot.id self.client.post("/admin/full_reindex") person = all_models.Person.query.get(person_id) snapshot = all_models.Snapshot.query.get(snapshot_id) self.assert_indexed_fields(snapshot, role_name, { "{}-email".format(person.id): person.email, "{}-name".format(person.id): person.name, "__sort__": person.email, })
def test_acl_update(self): """Test ACL column import with multiple emails.""" with factories.single_commit(): role_name = factories.AccessControlRoleFactory( object_type="Market").name emails = {factories.PersonFactory().email for _ in range(4)} update_emails = set(list(emails)[:2]) | {"*****@*****.**"} response = self.import_data( collections.OrderedDict([ ("object_type", "Market"), ("code", ""), ("title", "Title"), ("Admin", "*****@*****.**"), ("Assignee", "*****@*****.**"), ("Verifier", "*****@*****.**"), (role_name, "\n".join(emails)), ])) self._check_csv_response(response, {}) market = all_models.Market.query.filter_by(title="Title").first() response = self.import_data( collections.OrderedDict([ ("object_type", "Market"), ("code", market.slug), ("title", "Title"), ("Admin", "*****@*****.**"), (role_name, "\n".join(update_emails)), ])) self._check_csv_response(response, {}) market = models.Market.query.first() self.assertEqual( {person.email for person, _ in market.access_control_list}, update_emails, )
def test_acl_people(self, my_work_flags, should_return): """Owned returns objects where person has role with my_work set.""" with factories.single_commit(): for my_work in my_work_flags: role = factories.AccessControlRoleFactory(object_type="Control", my_work=my_work) acl = factories.AccessControlListFactory( ac_role=role, object=self.control, ) factories.AccessControlPersonFactory( ac_list=acl, person=self.person, ) control_id = self.control.id ids = self._get_first_result_set( { "object_name": "Control", "type": "ids", "filters": { "expression": { "object_name": "Person", "op": {"name": "owned"}, "ids": [self.person.id] } } }, "Control", "ids" ) if should_return: self.assertEqual(ids, [control_id]) else: self.assertEqual(ids, [])
def test_multiple_acl_roles_add(self, roles): """Test importing new object with multiple ACL roles.""" for email in self._random_emails: factories.PersonFactory(email=email) for role_name in roles.keys(): factories.AccessControlRoleFactory( object_type="Market", name=role_name + " ", ) import_dict = self._generate_role_import_dict(roles) self.import_data(import_dict) market = models.Market.query.first() stored_roles = {} for role_name in roles.keys(): stored_roles[role_name] = { acl.person.email for acl in market.access_control_list if acl.ac_role.name == role_name } self.assertEqual(stored_roles, roles)
def test_acr_control_export(self): """Test exporting of a AC roles with linked users.""" # pylint: disable=too-many-locals ac_roles = models.AccessControlRole.query.filter( models.AccessControlRole.object_type == "Control", models.AccessControlRole.internal == 0, ).all() control_acr_people = collections.defaultdict(dict) with factories.single_commit(): # Create one more custom role ac_roles.append( factories.AccessControlRoleFactory(object_type="Control")) controls = [ factories.ControlFactory(slug="Control {}".format(i)) for i in range(3) ] for control in controls: for ac_role in ac_roles: person = factories.PersonFactory() factories.AccessControlPersonFactory( ac_list=control.acr_acl_map[ac_role], person=person, ) control_acr_people[control.slug][ ac_role.name] = person.email audit = factories.AuditFactory() snapshots = self._create_snapshots(audit, controls) control_dicts = {} for snapshot, control in zip(snapshots, controls): # As revisions for snapshot are created using factories need to # update their content and rewrite acl snapshot.revision.content = control.log_json() for acl in snapshot.revision.content["access_control_list"]: acl["person"] = { "id": acl["person_id"], "type": "Person", } db.session.add(snapshot.revision) db.session.commit() control_dicts[control.slug] = { "Code": "*" + control.slug, "Revision Date": snapshot.revision.created_at.strftime(DATE_FORMAT_US), "Description": u"", "Effective Date": u"", "Fraud Related": u"", "Frequency": u"", "Kind/Nature": u"", "Notes": u"", "Reference URL": u"", "Review Status": u"some status", "Significance": u"", "State": u"Draft", "Last Assessment Date": u"", "Last Deprecated Date": u"", "Assessment Procedure": u"", "Title": control.title, "Type/Means": u"", "Audit": audit.slug, "Assertions": u",".join(json.loads(control.assertions)), "Categories": u"", "Document File": u"", 'Created Date': control.created_at.strftime(DATE_FORMAT_US), 'Last Updated Date': control.updated_at.strftime(DATE_FORMAT_US), 'Last Updated By': "", "Folder": u"", "Archived": u"yes" if audit.archived else u"no", } control_dicts[control.slug].update( **control_acr_people[control.slug]) search_request = [{ "object_name": "Snapshot", "filters": { "expression": { "left": "child_type", "op": { "name": "=" }, "right": "Control", }, }, }] parsed_data = self.export_parsed_csv( search_request)["Control Snapshot"] parsed_dict = {line["Code"]: line for line in parsed_data} for i, _ in enumerate(controls): self.assertEqual( parsed_dict["*Control {}".format(i)], control_dicts["Control {}".format(i)], )
def test_acr_control_export(self): """Test exporting of a AC roles with linked users.""" # pylint: disable=too-many-locals ac_roles = models.AccessControlRole.query.filter( models.AccessControlRole.object_type == "Control", models.AccessControlRole.internal == 0, ).all() control_acr_people = collections.defaultdict(dict) with factories.single_commit(): # Create one more custom role ac_roles.append( factories.AccessControlRoleFactory(object_type="Control")) controls = [ factories.ControlFactory(slug="Control {}".format(i)) for i in range(3) ] for control in controls: for ac_role in ac_roles: person = factories.PersonFactory() factories.AccessControlPersonFactory( ac_list=control.acr_acl_map[ac_role], person=person, ) control_acr_people[control.slug][ ac_role.name] = person.email audit = factories.AuditFactory() snapshots = self._create_snapshots(audit, controls) control_dicts = {} for snapshot, control in zip(snapshots, controls): # As revisions for snapshot are created using factories need to # update their content and rewrite acl snapshot.revision.content = control.log_json() for acl in snapshot.revision.content["access_control_list"]: acl["person"] = { "id": acl["person_id"], "type": "Person", } db.session.add(snapshot.revision) db.session.commit() control_dicts[control.slug] = self._control_dict({ "Code": "*" + control.slug, "Revision Date": snapshot.revision.created_at.strftime(DATE_FORMAT_US), "Title": control.title, "Audit": audit.slug, "Assertions": u",".join(json.loads(control.assertions)), 'Created Date': control.created_at.strftime(DATE_FORMAT_US), 'Last Updated Date': control.updated_at.strftime(DATE_FORMAT_US), "Archived": u"yes" if audit.archived else u"no", }) control_dicts[control.slug].update( **control_acr_people[control.slug]) parsed_data = self.export_parsed_csv( self.search_request)["Control Snapshot"] parsed_dict = {line["Code"]: line for line in parsed_data} for i, _ in enumerate(controls): self.assertEqual( parsed_dict["*Control {}".format(i)], control_dicts["Control {}".format(i)], )
def setUp(self): super(TestPermissions, self).setUp() self.api = Api() roles = {r.name: r for r in all_models.Role.query.all()} ac_roles = { r.name: r for r in all_models.AccessControlRole.query.all() } with factories.single_commit(): self.control = factories.ControlFactory() acrs = { "ACL_Reader": factories.AccessControlRoleFactory(name="ACL_Reader", object_type="Control", update=0), "ACL_Editor": factories.AccessControlRoleFactory(name="ACL_Editor", object_type="Control"), "ACL_Nobody": factories.AccessControlRoleFactory( name="ACL_Nobody", object_type="Control", read=0, update=0, delete=0, ), } 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(), "ACL_Nobody": 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.AccessControlListFactory(ac_role=ac_roles[role_name], object=self.program, person=person) self.proposal = factories.ProposalFactory( instance=self.control, content={ "access_control_list": {}, "custom_attribute_values": {}, "fields": {}, "mapping_fields": {}, "mapping_list_fields": {}, }) for role_name in ["ACL_Reader", "ACL_Editor", "ACL_Nobody"]: person = self.people[role_name] rbac_factories.UserRoleFactory(role=roles["Creator"], person=person) factories.AccessControlListFactory(ac_role=acrs[role_name], object=self.control, person=person) with factories.single_commit(): proposal_model.set_acl_to_all_proposals_for(self.control)
def test_apply_acl(self): # pylint: disable=too-many-locals """Test simple apply acl proposal.""" with factories.single_commit(): role_1 = factories.AccessControlRoleFactory( name="role_1", object_type="Control") role_2 = factories.AccessControlRoleFactory( name="role_2", object_type="Control") role_3 = factories.AccessControlRoleFactory( name="role_3", object_type="Control") role_4 = factories.AccessControlRoleFactory( name="role_4", object_type="Control") role_5 = factories.AccessControlRoleFactory( name="role_5", object_type="Control") with factories.single_commit(): control = factories.ControlFactory(title="1") person_1 = factories.PersonFactory() person_2 = factories.PersonFactory() person_3 = factories.PersonFactory() acl_1 = control.acr_acl_map[role_1] acl_2 = control.acr_acl_map[role_2] acl_3 = control.acr_acl_map[role_3] acl_4 = control.acr_acl_map[role_4] factories.AccessControlPersonFactory( ac_list=acl_1, person=person_1, ) factories.AccessControlPersonFactory( ac_list=acl_2, person=person_2, ) factories.AccessControlPersonFactory( ac_list=acl_3, person=person_3, ) for person in [person_1, person_2, person_3]: factories.AccessControlPersonFactory( ac_list=acl_4, person=person, ) with factories.single_commit(): proposal = factories.ProposalFactory( instance=control, content={ "access_control_list": { role_1.id: { "added": [{"id": person_2.id, "email": person_2.email}], "deleted": [] }, role_2.id: { "added": [{"id": person_1.id, "email": person_1.email}], "deleted": [{"id": person_2.id, "email": person_2.email}] }, role_3.id: { "added": [{"id": person_3.id, "email": person_3.email}], "deleted": [{"id": person_2.id, "email": person_2.email}] }, role_4.id: { "added": [], "deleted": [{"id": person_1.id, "email": person_1.email}, {"id": person_2.id, "email": person_2.email}, {"id": person_3.id, "email": person_3.email}] }, role_5.id: { "added": [{"id": person_1.id, "email": person_1.email}, {"id": person_2.id, "email": person_2.email}, {"id": person_3.id, "email": person_3.email}], "deleted": [], }, } }, agenda="agenda content") control_id = control.id person_1_id = person_1.id person_2_id = person_2.id person_3_id = person_3.id role_1_id = role_1.id role_2_id = role_2.id role_3_id = role_3.id role_4_id = role_4.id role_5_id = role_5.id self.assertEqual(proposal.STATES.PROPOSED, proposal.status) revisions = all_models.Revision.query.filter( all_models.Revision.resource_type == control.type, all_models.Revision.resource_id == control.id ).all() self.assertEqual(1, len(revisions)) resp = self.api.put( proposal, {"proposal": {"status": proposal.STATES.APPLIED}}) self.assert200(resp) control = all_models.Control.query.get(control_id) result_dict = collections.defaultdict(set) for person, acl in control.access_control_list: result_dict[acl.ac_role_id].add(person.id) self.assertEqual({person_1_id, person_2_id}, result_dict[role_1_id]) self.assertEqual({person_1_id}, result_dict[role_2_id]) self.assertEqual({person_3_id}, result_dict[role_3_id]) self.assertEqual(set([]), result_dict[role_4_id]) self.assertEqual({person_1_id, person_2_id, person_3_id}, result_dict[role_5_id])
def test_proposal_delete_acl(self, roles, deleted): """Test delete acl proposal for ACRs with internal flags as {roles}.""" role_person_list = [] with factories.single_commit(): risk = factories.RiskFactory(title="1") for idx, role_internal_flag in enumerate(roles): role = factories.AccessControlRoleFactory( name="role_{}".format(idx), object_type="Risk", internal=role_internal_flag) person = factories.PersonFactory() role_person_list.append((role, person)) acl = factories.AccessControlListFactory( ac_role=role, object=risk, ) factories.AccessControlPersonFactory( ac_list=acl, person=person, ) with factories.single_commit(): latest_revision = all_models.Revision.query.filter( all_models.Revision.resource_id == risk.id, all_models.Revision.resource_type == risk.type).order_by( all_models.Revision.created_at.desc()).first() latest_revision.content = risk.log_json() risk_id = risk.id risk_content = risk.log_json() risk_content["access_control_list"] = [] expected_result = {} for idx, (role, person) in enumerate(role_person_list): if deleted[idx]: expected_result[str(role.id)] = { "added": [], "deleted": [{ "id": person.id, "email": person.email }], } resp = self.api.post( all_models.Proposal, { "proposal": { "instance": { "id": risk.id, "type": risk.type, }, # "content": {"123": 123}, "full_instance_content": risk_content, "agenda": "delete access control roles", "context": None, } }) self.assertEqual(201, resp.status_code) risk = all_models.Risk.query.get(risk_id) self.assertEqual(1, len(risk.proposals)) self.assertIn("access_control_list", risk.proposals[0].content) acl = risk.proposals[0].content["access_control_list"] self.assertEqual(expected_result, acl) self.assertEqual(1, len(risk.comments))
def test_roleable_eager_query(self): """Test eager query on roleable object. This test compares the query counts while accessing an object with a single user role on it with an object with multiple users. """ with factories.single_commit(): people = [factories.PersonFactory() for _ in range(5)] emails = {person.email for person in people} control = factories.ControlFactory() control.add_person_with_role_name(people[0], "Admin") control_id = control.id db.session.expire_all() with utils.QueryCounter() as counter: control = all_models.Control.eager_query().filter_by( id=control_id ).one() eager_query_count = counter.get self.assertEqual(len(control.access_control_list), 1) self.assertEqual(eager_query_count, counter.get) self.assertEqual( control.access_control_list[0][1].ac_role.name, "Admin", ) self.assertEqual(eager_query_count, counter.get) self.assertEqual( control.access_control_list[0][0].email, people[0].email, ) self.assertEqual(eager_query_count, counter.get) factories.AccessControlRoleFactory(object_type="Control", name="custom") with factories.single_commit(): control_multi = factories.ControlFactory() for person in people: control_multi.add_person_with_role_name(person, "Admin") control_multi.add_person_with_role_name(person, "custom") control_multi_id = control_multi.id db.session.expire_all() with utils.QueryCounter() as counter: control_multi = all_models.Control.eager_query().filter_by( id=control_multi_id ).one() self.assertEqual(eager_query_count, counter.get) self.assertEqual( len(control_multi.access_control_list), len(people) * 2, ) self.assertEqual(eager_query_count, counter.get) admins = { person.email for person in control_multi.get_persons_for_rolename("Admin") } self.assertEqual(admins, emails) self.assertEqual(eager_query_count, counter.get) custom_role_users = { person.email for person in control_multi.get_persons_for_rolename("custom") } self.assertEqual(custom_role_users, emails) self.assertEqual(eager_query_count, counter.get)
def setUp(self): super(TestAccessControlRoleable, self).setUp() with factories.single_commit(): self.role = factories.AccessControlRoleFactory(object_type="Control") self.person = factories.PersonFactory()
def test_email_sending(self): """Test sending emails about proposals.""" role_1 = factories.AccessControlRoleFactory(object_type="Program", notify_about_proposal=True) role_2 = factories.AccessControlRoleFactory(object_type="Program", notify_about_proposal=True) role_3 = factories.AccessControlRoleFactory( object_type="Program", notify_about_proposal=False) with factories.single_commit(): program = factories.ProgramFactory() person_1 = factories.PersonFactory() # has 1 role person_2 = factories.PersonFactory() # has no roles person_3 = factories.PersonFactory() # has 2 roles factories.PersonFactory() # not related to program at all factories.AccessControlPersonFactory( ac_list=program.acr_acl_map[role_1], person=person_1) factories.AccessControlPersonFactory( ac_list=program.acr_acl_map[role_1], person=person_3) factories.AccessControlPersonFactory( ac_list=program.acr_acl_map[role_2], person=person_3) factories.AccessControlPersonFactory( ac_list=program.acr_acl_map[role_3], person=person_2) proposal_1 = factories.ProposalFactory( instance=program, content={ "fields": { "title": "a" }, "access_control_list": {}, "custom_attribute_values": {}, "mapping_fields": {}, "mapping_list_fields": {}, }, agenda="agenda 1") proposal_2 = factories.ProposalFactory( instance=program, content={ "fields": { "title": "b" }, "access_control_list": {}, "custom_attribute_values": {}, "mapping_fields": {}, "mapping_list_fields": {}, }, agenda="agenda 2") self.assertIsNone(proposal_1.proposed_notified_datetime) self.assertIsNone(proposal_2.proposed_notified_datetime) with mock.patch("google.appengine.api.mail.send_mail") as mailer_mock: with mock.patch.object(fast_digest.DIGEST_TMPL, "render") as bodybuilder_mock: fast_digest.send_notification() self.assertIsNotNone(proposal_1.proposed_notified_datetime) self.assertIsNotNone(proposal_2.proposed_notified_datetime) self.assertEqual(2, len(bodybuilder_mock.call_args_list)) self.assertEqual(2, len(mailer_mock.call_args_list)) # email to each required person self.assertListEqual( sorted([person_1.email, person_3.email]), sorted([a[1]["to"] for a in mailer_mock.call_args_list])) # no matter how many roles each proposal should be otified # only once for that person self.assertListEqual( [2] * 2, [len(a[1]["proposals"]) for a in bodybuilder_mock.call_args_list])
def test_apply_acl(self): # pylint: disable=too-many-locals """Test simple apply acl proposal.""" with factories.single_commit(): control = factories.ControlFactory(title="1") role_1 = factories.AccessControlRoleFactory(name="role_1", object_type="Control") role_2 = factories.AccessControlRoleFactory(name="role_2", object_type="Control") role_3 = factories.AccessControlRoleFactory(name="role_3", object_type="Control") role_4 = factories.AccessControlRoleFactory(name="role_4", object_type="Control") role_5 = factories.AccessControlRoleFactory(name="role_5", object_type="Control") person_1 = factories.PersonFactory() person_2 = factories.PersonFactory() person_3 = factories.PersonFactory() factories.AccessControlListFactory( person=person_1, ac_role=role_1, object=control, ) factories.AccessControlListFactory( person=person_2, ac_role=role_2, object=control, ) factories.AccessControlListFactory( person=person_3, ac_role=role_3, object=control, ) for person in [person_1, person_2, person_3]: factories.AccessControlListFactory( person=person, ac_role=role_4, object=control, ) with factories.single_commit(): proposal = factories.ProposalFactory(instance=control, content={ "access_control_list": { role_1.id: { "added": [{ "id": person_2.id, "email": person_2.email }], "deleted": [] }, role_2.id: { "added": [{ "id": person_1.id, "email": person_1.email }], "deleted": [{ "id": person_2.id, "email": person_2.email }] }, role_3.id: { "added": [{ "id": person_3.id, "email": person_3.email }], "deleted": [{ "id": person_2.id, "email": person_2.email }] }, role_4.id: { "added": [], "deleted": [{ "id": person_1.id, "email": person_1.email }, { "id": person_2.id, "email": person_2.email }, { "id": person_3.id, "email": person_3.email }] }, role_5.id: { "added": [{ "id": person_1.id, "email": person_1.email }, { "id": person_2.id, "email": person_2.email }, { "id": person_3.id, "email": person_3.email }], "deleted": [], }, } }, agenda="agenda content") control_id = control.id person_1_id = person_1.id person_2_id = person_2.id person_3_id = person_3.id role_1_id = role_1.id role_2_id = role_2.id role_3_id = role_3.id role_4_id = role_4.id role_5_id = role_5.id self.assertEqual(proposal.STATES.PROPOSED, proposal.status) with self.number_obj_revisions_for(control): self.apply_proposal(proposal) control = all_models.Control.query.get(control_id) result_dict = collections.defaultdict(set) for acl in control.access_control_list: result_dict[acl.ac_role_id].add(acl.person_id) self.assertEqual({person_1_id, person_2_id}, result_dict[role_1_id]) self.assertEqual({person_1_id}, result_dict[role_2_id]) self.assertEqual({person_3_id}, result_dict[role_3_id]) self.assertEqual(set([]), result_dict[role_4_id]) self.assertEqual({person_1_id, person_2_id, person_3_id}, result_dict[role_5_id])