class GeoRevIncr(OTMTestCase): def setUp(self): self.instance = make_instance() self.user = make_commander_user(self.instance) self.plot = Plot(geom=Point(0, 0), instance=self.instance) self.plot.save_with_user(self.user) def _hash_and_rev(self): i = Instance.objects.get(pk=self.instance.pk) return [i.geo_rev_hash, i.geo_rev] @contextmanager def _assert_updates_geo_rev(self, update_expected=True): rev1h, rev1 = self._hash_and_rev() yield rev2h, rev2 = self._hash_and_rev() if update_expected: self.assertNotEqual(rev1h, rev2h) self.assertEqual(rev1 + 1, rev2) else: self.assertEqual(rev1h, rev2h) self.assertEqual(rev1, rev2) def test_create(self): with self._assert_updates_geo_rev(): plot = Plot(instance=self.instance) request_dict = {'plot.geom': {'x': 0, 'y': 0}} update_map_feature(request_dict, self.user, plot) plot.save_with_user(self.user) def test_move(self): with self._assert_updates_geo_rev(): request_dict = {'plot.geom': {'x': 5, 'y': 5}} update_map_feature(request_dict, self.user, self.plot) self.plot.save_with_user(self.user) def test_update_without_move(self): with self._assert_updates_geo_rev(False): request_dict = {'plot.address_zip': '19119'} update_map_feature(request_dict, self.user, self.plot) self.plot.save_with_user(self.user) def test_delete(self): with self._assert_updates_geo_rev(): self.plot.delete_with_user(self.user)
def test_changing_geometry_updates_counter(self): rev1h, rev1 = self.hash_and_rev() # Create plot1 = Plot(geom=self.p1, instance=self.instance) plot1.save_with_user(self.user) rev2h, rev2 = self.hash_and_rev() self.assertNotEqual(rev1h, rev2h) self.assertEqual(rev1 + 1, rev2) plot2 = Plot(geom=self.p2, instance=self.instance) plot2.save_with_user(self.user) rev3h, rev3 = self.hash_and_rev() self.assertNotEqual(rev2h, rev3h) self.assertEqual(rev2 + 1, rev3) # Update plot2.geom = self.p1 plot2.save_with_user(self.user) rev4h, rev4 = self.hash_and_rev() self.assertNotEqual(rev3h, rev4h) self.assertEqual(rev3 + 1, rev4) # Delete plot2.delete_with_user(self.user) rev5h, rev5 = self.hash_and_rev() self.assertNotEqual(rev4h, rev5h) self.assertEqual(rev4 + 1, rev5)
class UserRoleModelPermissionTest(MultiUserTestCase): def setUp(self): super(UserRoleModelPermissionTest, self).setUp() self.plot = Plot(geom=self.p1, instance=self.instance) self.plot.save_with_user(self.direct_user) self.tree = Tree(plot=self.plot, instance=self.instance) self.tree.save_with_user(self.direct_user) def _change_user_role(self, user, role): iuser = user.get_instance_user(self.instance) iuser.role = role iuser.save_with_user(self.commander_user) def test_save_new_object_authorized_officer(self): ''' Save two new objects with authorized user, nothing should happen''' plot = Plot(geom=self.p1, instance=self.instance) plot.save_with_user(self.direct_user) tree = Tree(plot=plot, instance=self.instance) tree.save_with_user(self.direct_user) def test_save_new_object_authorized_conjurer(self): ''' Save two new objects with authorized user, nothing should happen''' plot = Plot(geom=self.p1, instance=self.instance) plot.save_with_user(self.conjurer_user) tree = Tree(plot=plot, instance=self.instance) tree.save_with_user(self.conjurer_user) def test_save_new_object_unauthorized_outlaw(self): plot = Plot(geom=self.p1, instance=self.instance) self.assertRaises(AuthorizeException, plot.save_with_user, self.outlaw_user) plot.save_base() tree = Tree(plot=plot, instance=self.instance) self.assertRaises(AuthorizeException, tree.save_with_user, self.outlaw_user) def test_save_new_object_unauthorized_tweaker(self): plot = Plot(geom=self.p1, instance=self.instance) self.assertRaises(AuthorizeException, plot.save_with_user, self.tweaker_user) plot.save_base() tree = Tree(plot=plot, instance=self.instance) self.assertRaises(AuthorizeException, tree.save_with_user, self.tweaker_user) def test_assign_commander_role_can_delete(self): with self.assertRaises(AuthorizeException): self.tree.delete_with_user(self.outlaw_user) self._change_user_role( self.outlaw_user, make_commander_role(self.tree.get_instance())) self.tree.delete_with_user(self.outlaw_user) self.assertEqual(Tree.objects.count(), 0) def test_delete_object(self): with self.assertRaises(AuthorizeException): self.tree.delete_with_user(self.outlaw_user) self.tree.delete_with_user(self.commander_user) with self.assertRaises(AuthorizeException): self.plot.delete_with_user(self.outlaw_user, cascade=True) self.plot.delete_with_user(self.commander_user, cascade=True) def test_delete_object_you_created(self): outlaw_role = self.outlaw_user.get_role(self.instance) self._change_user_role(self.direct_user, outlaw_role) self.tree.delete_with_user(self.direct_user) self.plot.delete_with_user(self.direct_user, cascade=True)
class ReviewTest(MultiUserTestCase): def setUp(self): super(ReviewTest, self).setUp() self.plot = Plot(geom=self.p1, instance=self.instance) self.plot.save_with_user(self.commander_user) def test_simple_approve(self): self.plot.width = 444 self.plot.save_with_user(self.commander_user) width_audit = self.plot.audits().order_by('-created')[0] # Sanity check self.assertEqual(width_audit.field, 'width') # Should not have a reference associated with it self.assertIsNone(width_audit.ref) approve_or_reject_existing_edit( width_audit, self.commander_user, approved=True) width_audit_reloaded = Audit.objects.get(pk=width_audit.pk) self.assertIsNotNone(width_audit_reloaded.ref) refd = width_audit_reloaded.ref self.assertEqual(refd.action, Audit.Type.ReviewApprove) def test_reject_regular_edit(self): self.plot.width = 444 self.plot.save_with_user(self.commander_user) self.plot.width = 555 self.plot.save_with_user(self.commander_user) width_audit = self.plot.audits().order_by('-created')[0] # Sanity check self.assertEqual(width_audit.field, 'width') # Should not have a reference associated with it self.assertIsNone(width_audit.ref) approve_or_reject_existing_edit( width_audit, self.commander_user, approved=False) width_audit_reloaded = Audit.objects.get(pk=width_audit.pk) self.assertIsNotNone(width_audit_reloaded.ref) refd = width_audit_reloaded.ref self.assertEqual(refd.action, Audit.Type.ReviewReject) plot_reloaded = Plot.objects.get(pk=self.plot.pk) self.assertEqual(plot_reloaded.width, 444) def test_reject_id_edit(self): id_audit = self.plot.audits().get(field='id') approve_or_reject_existing_edit( id_audit, self.commander_user, approved=False) all_audits = list(self.plot.audits()) self.assertNotEqual(len(all_audits), 0) updated_audit = Audit.objects.get(pk=id_audit.pk) ref_audit = updated_audit.ref self.assertIsNotNone(ref_audit) self.assertEqual(ref_audit.action, Audit.Type.ReviewReject) self.assertRaises(Plot.DoesNotExist, Plot.objects.get, pk=self.plot.pk) def test_requires_write_permissions_on_field(self): self.plot.width = 333 self.plot.save_with_user(self.commander_user) width_audit = self.plot.audits().order_by('-created')[0] # Read only can't edit FieldPermission.objects.filter(field_name='width').update( permission_level=FieldPermission.READ_ONLY) self.assertRaises(AuthorizeException, approve_or_reject_existing_edit, width_audit, self.commander_user, approved=True) # Neither can 'write with audit' FieldPermission.objects.filter(field_name='width').update( permission_level=FieldPermission.WRITE_WITH_AUDIT) self.assertRaises(AuthorizeException, approve_or_reject_existing_edit, width_audit, self.commander_user, approved=True) # But write directly can FieldPermission.objects.filter(field_name='width').update( permission_level=FieldPermission.WRITE_DIRECTLY) approve_or_reject_existing_edit( width_audit, self.commander_user, approved=True) def test_reject_or_approve_pending_edit_fails(self): FieldPermission.objects.filter(field_name='width').update( permission_level=FieldPermission.WRITE_WITH_AUDIT) self.plot.width = 333 self.plot.save_with_user(self.commander_user) pdg_width_audit = self.plot.audits().order_by('-created')[0] FieldPermission.objects.filter(field_name='width').update( permission_level=FieldPermission.WRITE_DIRECTLY) self.assertRaises(Exception, approve_or_reject_existing_edit, pdg_width_audit, self.commander_user, approved=True) def test_rejecting_old_edits_doesnt_update_object(self): self.plot.width = 333 self.plot.save_with_user(self.commander_user) self.plot.width = 444 self.plot.save_with_user(self.commander_user) width_audit = self.plot.audits().order_by('-created')[0] self.plot.width = 555 self.plot.save_with_user(self.commander_user) approve_or_reject_existing_edit( width_audit, self.commander_user, approved=False) reloaded_plot = Plot.objects.get(pk=self.plot.pk) self.assertEqual(reloaded_plot.width, 555) def test_approving_edits_on_deleted_obj_doesnt_fail(self): self.plot.width = 444 self.plot.save_with_user(self.commander_user) width_audit = self.plot.audits().order_by('-created')[0] self.plot.delete_with_user(self.commander_user, cascade=True) approve_or_reject_existing_edit( width_audit, self.commander_user, approved=False)
class UserRoleFieldPermissionTest(OTMTestCase): def setUp(self): self.p1 = Point(-8515941.0, 4953519.0) self.instance = make_instance(point=self.p1) self.commander = make_commander_user(self.instance) self.officer = make_officer_user(self.instance) self.observer = make_observer_user(self.instance) self.outlaw = make_user_with_default_role(self.instance, 'outlaw') self.plot = Plot(geom=self.p1, instance=self.instance) self.plot.save_with_user(self.officer) self.tree = Tree(plot=self.plot, instance=self.instance) self.tree.save_with_user(self.officer) def test_no_permission_cant_edit_object(self): self.plot.length = 10 self.assertRaises(AuthorizeException, self.plot.save_with_user, self.outlaw) self.assertNotEqual(Plot.objects.get(pk=self.plot.pk).length, 10) self.tree.diameter = 10 self.assertRaises(AuthorizeException, self.tree.save_with_user, self.outlaw) self.assertNotEqual(Tree.objects.get(pk=self.tree.pk).diameter, 10) def test_readonly_cant_edit_object(self): self.plot.length = 10 self.assertRaises(AuthorizeException, self.plot.save_with_user, self.observer) self.assertNotEqual(Plot.objects.get(pk=self.plot.pk).length, 10) self.tree.diameter = 10 self.assertRaises(AuthorizeException, self.tree.save_with_user, self.observer) self.assertNotEqual(Tree.objects.get(pk=self.tree.pk).diameter, 10) def test_writeperm_allows_write(self): self.plot.length = 10 self.plot.save_with_user(self.officer) self.assertEqual(Plot.objects.get(pk=self.plot.pk).length, 10) self.tree.diameter = 10 self.tree.save_with_user(self.officer) self.assertEqual(Tree.objects.get(pk=self.tree.pk).diameter, 10) def test_save_new_object_authorized(self): '''Save two new objects with authorized user, nothing should happen''' plot = Plot(geom=self.p1, instance=self.instance) plot.save_with_user(self.officer) tree = Tree(plot=plot, instance=self.instance) tree.save_with_user(self.officer) def test_save_new_object_unauthorized(self): plot = Plot(geom=self.p1, instance=self.instance) self.assertRaises(AuthorizeException, plot.save_with_user, self.outlaw) plot.save_base() tree = Tree(plot=plot, instance=self.instance) self.assertRaises(AuthorizeException, tree.save_with_user, self.outlaw) def test_make_administrator_can_delete(self): with self.assertRaises(AuthorizeException): self.tree.delete_with_user(self.outlaw) iuser = self.outlaw.get_instance_user(self.instance) role = Role.objects.create(instance=self.instance, name=Role.ADMINISTRATOR, rep_thresh=0) iuser.role = role iuser.save_with_user(self.commander) self.tree.delete_with_user(self.outlaw) self.assertEqual(Tree.objects.count(), 0) def test_delete_object(self): with self.assertRaises(AuthorizeException): self.tree.delete_with_user(self.outlaw) with self.assertRaises(AuthorizeException): self.plot.delete_with_user(self.outlaw, cascade=True) with self.assertRaises(AuthorizeException): self.tree.delete_with_user(self.officer) with self.assertRaises(AuthorizeException): self.plot.delete_with_user(self.officer, cascade=True) self.tree.delete_with_user(self.commander) self.plot.delete_with_user(self.commander, cascade=True) def test_masking_authorized(self): "When masking with a superuser, nothing should happen" self.plot.width = 5 self.plot.save_with_user(self.commander) plot = Plot.objects.get(pk=self.plot.pk) plot.mask_unauthorized_fields(self.commander) self.assertEqual(self.plot.width, plot.width) def test_masking_unauthorized(self): "Masking changes an unauthorized field to None" self.plot.width = 5 self.plot.save_base() plot = Plot.objects.get(pk=self.plot.pk) plot.mask_unauthorized_fields(self.observer) self.assertEqual(None, plot.width) plot = Plot.objects.get(pk=self.plot.pk) plot.mask_unauthorized_fields(self.outlaw) self.assertEqual(None, plot.width) def test_masking_whole_queryset(self): "Masking also works on entire querysets" self.plot.width = 5 self.plot.save_base() plots = Plot.objects.filter(pk=self.plot.pk) plot = Plot.mask_queryset(plots, self.observer)[0] self.assertEqual(None, plot.width) def test_write_fails_if_any_fields_cant_be_written(self): """ If a user tries to modify several fields simultaneously, only some of which s/he has access to, the write will fail for all fields.""" self.plot.length = 10 self.plot.width = 110 self.assertRaises(AuthorizeException, self.plot.save_with_user, self.officer) self.assertNotEqual(Plot.objects.get(pk=self.plot.pk).length, 10) self.assertNotEqual(Plot.objects.get(pk=self.plot.pk).width, 110) self.tree.diameter = 10 self.tree.canopy_height = 110 self.assertRaises(AuthorizeException, self.tree.save_with_user, self.officer) self.assertNotEqual(Tree.objects.get(pk=self.tree.pk).diameter, 10) self.assertNotEqual(Tree.objects.get(pk=self.tree.pk).canopy_height, 110)
class GeoAndEcoRevIncr(OTMTestCase): def setUp(self): self.instance = make_instance() self.user = make_commander_user(self.instance) self.plot = Plot(geom=Point(0, 0), instance=self.instance) self.plot.save_with_user(self.user) def _hash_and_revs(self): i = Instance.objects.get(pk=self.instance.pk) return [i.geo_rev_hash, i.geo_rev, i.eco_rev] @contextmanager def _assert_updates_geo_and_eco_rev(self, update_expected=True): geo_rev1h, geo_rev1, eco_rev1 = self._hash_and_revs() yield geo_rev2h, geo_rev2, eco_rev2 = self._hash_and_revs() if update_expected: self.assertNotEqual(geo_rev1h, geo_rev2h) self.assertEqual(geo_rev1 + 1, geo_rev2) self.assertEqual(eco_rev1 + 1, eco_rev2) else: self.assertEqual(geo_rev1h, geo_rev2h) self.assertEqual(geo_rev1, geo_rev2) self.assertEqual(eco_rev1, eco_rev2) def test_create_plot(self): with self._assert_updates_geo_and_eco_rev(): plot = Plot(instance=self.instance) request_dict = {'plot.geom': {'x': 0, 'y': 0}} update_map_feature(request_dict, self.user, plot) @skip('Disabling until we figure out why it is failing on CI server') def test_create_bioswale(self): self.instance.add_map_feature_types(['Bioswale']) with self._assert_updates_geo_and_eco_rev(): bioswale = Bioswale(instance=self.instance) request_dict = { 'plot.geom': { 'x': 0, 'y': 0 }, 'bioswale.polygon': { 'polygon': [[0, 0], [1, 0], [1, 1], [0, 1], [0, 0]] } } update_map_feature(request_dict, self.user, bioswale) with self._assert_updates_geo_and_eco_rev(): request_dict = { 'bioswale.polygon': { 'polygon': [[0, 0], [2, 0], [2, 2], [0, 2], [0, 0]] } } update_map_feature(request_dict, self.user, bioswale) def test_move(self): with self._assert_updates_geo_and_eco_rev(): request_dict = {'plot.geom': {'x': 5, 'y': 5}} update_map_feature(request_dict, self.user, self.plot) def test_update_without_move(self): with self._assert_updates_geo_and_eco_rev(False): request_dict = {'plot.address_zip': '19119'} update_map_feature(request_dict, self.user, self.plot) def test_delete(self): with self._assert_updates_geo_and_eco_rev(): self.plot.delete_with_user(self.user)
class GeoAndEcoRevIncr(OTMTestCase): def setUp(self): self.instance = make_instance() self.user = make_commander_user(self.instance) self.plot = Plot(geom=Point(0, 0), instance=self.instance) self.plot.save_with_user(self.user) def _hash_and_revs(self): i = Instance.objects.get(pk=self.instance.pk) return [i.geo_rev_hash, i.geo_rev, i.eco_rev] @contextmanager def _assert_updates_geo_and_eco_rev(self, update_expected=True): geo_rev1h, geo_rev1, eco_rev1 = self._hash_and_revs() yield geo_rev2h, geo_rev2, eco_rev2 = self._hash_and_revs() if update_expected: self.assertNotEqual(geo_rev1h, geo_rev2h) self.assertEqual(geo_rev1 + 1, geo_rev2) self.assertEqual(eco_rev1 + 1, eco_rev2) else: self.assertEqual(geo_rev1h, geo_rev2h) self.assertEqual(geo_rev1, geo_rev2) self.assertEqual(eco_rev1, eco_rev2) def test_create_plot(self): with self._assert_updates_geo_and_eco_rev(): plot = Plot(instance=self.instance) request_dict = {'plot.geom': {'x': 0, 'y': 0}} update_map_feature(request_dict, self.user, plot) def test_create_bioswale(self): self.instance.add_map_feature_types(['Bioswale']) with self._assert_updates_geo_and_eco_rev(): bioswale = Bioswale(instance=self.instance) request_dict = { 'plot.geom': {'x': 0, 'y': 0}, 'bioswale.polygon': {'polygon': [ [0, 0], [1, 0], [1, 1], [0, 1], [0, 0]]} } update_map_feature(request_dict, self.user, bioswale) with self._assert_updates_geo_and_eco_rev(): request_dict = { 'bioswale.polygon': {'polygon': [ [0, 0], [2, 0], [2, 2], [0, 2], [0, 0]]}} update_map_feature(request_dict, self.user, bioswale) def test_move(self): with self._assert_updates_geo_and_eco_rev(): request_dict = {'plot.geom': {'x': 5, 'y': 5}} update_map_feature(request_dict, self.user, self.plot) def test_update_without_move(self): with self._assert_updates_geo_and_eco_rev(False): request_dict = {'plot.address_zip': '19119'} update_map_feature(request_dict, self.user, self.plot) def test_delete(self): with self._assert_updates_geo_and_eco_rev(): self.plot.delete_with_user(self.user)
class UserRoleFieldPermissionTest(OTMTestCase): def setUp(self): self.p1 = Point(-8515941.0, 4953519.0) self.instance = make_instance(point=self.p1) self.commander = make_commander_user(self.instance) self.officer = make_officer_user(self.instance) self.observer = make_observer_user(self.instance) self.outlaw = make_user_with_default_role(self.instance, 'outlaw') self.plot = Plot(geom=self.p1, instance=self.instance) self.plot.save_with_user(self.officer) self.tree = Tree(plot=self.plot, instance=self.instance) self.tree.save_with_user(self.officer) def test_no_permission_cant_edit_object(self): self.plot.length = 10 self.assertRaises(AuthorizeException, self.plot.save_with_user, self.outlaw) self.assertNotEqual(Plot.objects.get(pk=self.plot.pk).length, 10) self.tree.diameter = 10 self.assertRaises(AuthorizeException, self.tree.save_with_user, self.outlaw) self.assertNotEqual(Tree.objects.get(pk=self.tree.pk).diameter, 10) def test_readonly_cant_edit_object(self): self.plot.length = 10 self.assertRaises(AuthorizeException, self.plot.save_with_user, self.observer) self.assertNotEqual(Plot.objects.get(pk=self.plot.pk).length, 10) self.tree.diameter = 10 self.assertRaises(AuthorizeException, self.tree.save_with_user, self.observer) self.assertNotEqual(Tree.objects.get(pk=self.tree.pk).diameter, 10) def test_writeperm_allows_write(self): self.plot.length = 10 self.plot.save_with_user(self.officer) self.assertEqual(Plot.objects.get(pk=self.plot.pk).length, 10) self.tree.diameter = 10 self.tree.save_with_user(self.officer) self.assertEqual(Tree.objects.get(pk=self.tree.pk).diameter, 10) def test_save_new_object_authorized(self): '''Save two new objects with authorized user, nothing should happen''' plot = Plot(geom=self.p1, instance=self.instance) plot.save_with_user(self.officer) tree = Tree(plot=plot, instance=self.instance) tree.save_with_user(self.officer) def test_save_new_object_unauthorized(self): plot = Plot(geom=self.p1, instance=self.instance) self.assertRaises(AuthorizeException, plot.save_with_user, self.outlaw) plot.save_base() tree = Tree(plot=plot, instance=self.instance) self.assertRaises(AuthorizeException, tree.save_with_user, self.outlaw) def test_make_administrator_can_delete(self): with self.assertRaises(AuthorizeException): self.tree.delete_with_user(self.outlaw) iuser = self.outlaw.get_instance_user(self.instance) role = Role.objects.create(instance=self.instance, name=Role.ADMINISTRATOR, rep_thresh=0) iuser.role = role iuser.save_with_user(self.commander) self.tree.delete_with_user(self.outlaw) self.assertEqual(Tree.objects.count(), 0) def test_delete_object(self): with self.assertRaises(AuthorizeException): self.tree.delete_with_user(self.outlaw) with self.assertRaises(AuthorizeException): self.plot.delete_with_user(self.outlaw, cascade=True) with self.assertRaises(AuthorizeException): self.tree.delete_with_user(self.officer) with self.assertRaises(AuthorizeException): self.plot.delete_with_user(self.officer, cascade=True) self.tree.delete_with_user(self.commander) self.plot.delete_with_user(self.commander, cascade=True) def test_masking_authorized(self): "When masking with a superuser, nothing should happen" self.plot.width = 5 self.plot.save_with_user(self.commander) plot = Plot.objects.get(pk=self.plot.pk) plot.mask_unauthorized_fields(self.commander) self.assertEqual(self.plot.width, plot.width) def test_masking_unauthorized(self): "Masking changes an unauthorized field to None" self.plot.width = 5 self.plot.save_base() plot = Plot.objects.get(pk=self.plot.pk) plot.mask_unauthorized_fields(self.observer) self.assertEqual(None, plot.width) plot = Plot.objects.get(pk=self.plot.pk) plot.mask_unauthorized_fields(self.outlaw) self.assertEqual(None, plot.width) def test_masking_whole_queryset(self): "Masking also works on entire querysets" self.plot.width = 5 self.plot.save_base() plots = Plot.objects.filter(pk=self.plot.pk) plot = Plot.mask_queryset(plots, self.observer)[0] self.assertEqual(None, plot.width) def test_write_fails_if_any_fields_cant_be_written(self): """ If a user tries to modify several fields simultaneously, only some of which s/he has access to, the write will fail for all fields.""" self.plot.length = 10 self.plot.width = 110 self.assertRaises(AuthorizeException, self.plot.save_with_user, self.officer) self.assertNotEqual(Plot.objects.get(pk=self.plot.pk).length, 10) self.assertNotEqual(Plot.objects.get(pk=self.plot.pk).width, 110) self.tree.diameter = 10 self.tree.canopy_height = 110 self.assertRaises(AuthorizeException, self.tree.save_with_user, self.officer) self.assertNotEqual(Tree.objects.get(pk=self.tree.pk).diameter, 10) self.assertNotEqual( Tree.objects.get(pk=self.tree.pk).canopy_height, 110)