OLD | NEW |
(Empty) | |
| 1 # Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is govered by a BSD-style |
| 3 # license that can be found in the LICENSE file or at |
| 4 # https://developers.google.com/open-source/licenses/bsd |
| 5 |
| 6 """Tests for permissions.py.""" |
| 7 |
| 8 import time |
| 9 import unittest |
| 10 |
| 11 import mox |
| 12 |
| 13 import settings |
| 14 from framework import framework_constants |
| 15 from framework import framework_views |
| 16 from framework import monorailrequest |
| 17 from framework import permissions |
| 18 from proto import project_pb2 |
| 19 from proto import site_pb2 |
| 20 from proto import tracker_pb2 |
| 21 from proto import user_pb2 |
| 22 from proto import usergroup_pb2 |
| 23 from testing import fake |
| 24 from testing import testing_helpers |
| 25 from tracker import tracker_bizobj |
| 26 |
| 27 |
| 28 class PermissionSetTest(unittest.TestCase): |
| 29 |
| 30 def setUp(self): |
| 31 self.perms = permissions.PermissionSet(['A', 'b', 'Cc']) |
| 32 self.proj = project_pb2.Project() |
| 33 self.proj.contributor_ids.append(111L) |
| 34 self.proj.contributor_ids.append(222L) |
| 35 self.proj.extra_perms.append(project_pb2.Project.ExtraPerms( |
| 36 member_id=111L, perms=['Cc', 'D', 'e', 'Ff'])) |
| 37 self.proj.extra_perms.append(project_pb2.Project.ExtraPerms( |
| 38 member_id=222L, perms=['G', 'H'])) |
| 39 # user 3 used to be a member and had extra perms, but no longer in project. |
| 40 self.proj.extra_perms.append(project_pb2.Project.ExtraPerms( |
| 41 member_id=333L, perms=['G', 'H'])) |
| 42 |
| 43 def testGetAttr(self): |
| 44 self.assertTrue(self.perms.a) |
| 45 self.assertTrue(self.perms.A) |
| 46 self.assertTrue(self.perms.b) |
| 47 self.assertTrue(self.perms.Cc) |
| 48 self.assertTrue(self.perms.CC) |
| 49 |
| 50 self.assertFalse(self.perms.z) |
| 51 self.assertFalse(self.perms.Z) |
| 52 |
| 53 def testCanUsePerm_Anonymous(self): |
| 54 effective_ids = set() |
| 55 self.assertTrue(self.perms.CanUsePerm('A', effective_ids, self.proj, [])) |
| 56 self.assertFalse(self.perms.CanUsePerm('D', effective_ids, self.proj, [])) |
| 57 self.assertFalse(self.perms.CanUsePerm('Z', effective_ids, self.proj, [])) |
| 58 |
| 59 def testCanUsePerm_SignedInNoGroups(self): |
| 60 effective_ids = {111L} |
| 61 self.assertTrue(self.perms.CanUsePerm('A', effective_ids, self.proj, [])) |
| 62 self.assertTrue(self.perms.CanUsePerm('D', effective_ids, self.proj, [])) |
| 63 self.assertTrue(self.perms.CanUsePerm( |
| 64 'D', effective_ids, self.proj, ['Restrict-D-A'])) |
| 65 self.assertFalse(self.perms.CanUsePerm('G', effective_ids, self.proj, [])) |
| 66 self.assertFalse(self.perms.CanUsePerm('Z', effective_ids, self.proj, [])) |
| 67 |
| 68 effective_ids = {222L} |
| 69 self.assertTrue(self.perms.CanUsePerm('A', effective_ids, self.proj, [])) |
| 70 self.assertFalse(self.perms.CanUsePerm('D', effective_ids, self.proj, [])) |
| 71 self.assertTrue(self.perms.CanUsePerm('G', effective_ids, self.proj, [])) |
| 72 self.assertFalse(self.perms.CanUsePerm('Z', effective_ids, self.proj, [])) |
| 73 self.assertFalse(self.perms.CanUsePerm( |
| 74 'Z', effective_ids, self.proj, ['Restrict-Z-A'])) |
| 75 |
| 76 def testCanUsePerm_SignedInWithGroups(self): |
| 77 effective_ids = {111L, 222L, 333L} |
| 78 self.assertTrue(self.perms.CanUsePerm('A', effective_ids, self.proj, [])) |
| 79 self.assertTrue(self.perms.CanUsePerm('D', effective_ids, self.proj, [])) |
| 80 self.assertTrue(self.perms.CanUsePerm('G', effective_ids, self.proj, [])) |
| 81 self.assertTrue(self.perms.CanUsePerm( |
| 82 'G', effective_ids, self.proj, ['Restrict-G-D'])) |
| 83 self.assertFalse(self.perms.CanUsePerm('Z', effective_ids, self.proj, [])) |
| 84 self.assertFalse(self.perms.CanUsePerm( |
| 85 'G', effective_ids, self.proj, ['Restrict-G-Z'])) |
| 86 |
| 87 def testCanUsePerm_FormerMember(self): |
| 88 effective_ids = {333L} |
| 89 self.assertTrue(self.perms.CanUsePerm('A', effective_ids, self.proj, [])) |
| 90 self.assertFalse(self.perms.CanUsePerm('D', effective_ids, self.proj, [])) |
| 91 self.assertFalse(self.perms.CanUsePerm('G', effective_ids, self.proj, [])) |
| 92 self.assertFalse(self.perms.CanUsePerm('Z', effective_ids, self.proj, [])) |
| 93 |
| 94 def testHasPerm_InPermSet(self): |
| 95 self.assertTrue(self.perms.HasPerm('a', 0, None)) |
| 96 self.assertTrue(self.perms.HasPerm('a', 0, self.proj)) |
| 97 self.assertTrue(self.perms.HasPerm('A', 0, None)) |
| 98 self.assertTrue(self.perms.HasPerm('A', 0, self.proj)) |
| 99 self.assertFalse(self.perms.HasPerm('Z', 0, None)) |
| 100 self.assertFalse(self.perms.HasPerm('Z', 0, self.proj)) |
| 101 |
| 102 def testHasPerm_InExtraPerms(self): |
| 103 self.assertTrue(self.perms.HasPerm('d', 111L, self.proj)) |
| 104 self.assertTrue(self.perms.HasPerm('D', 111L, self.proj)) |
| 105 self.assertTrue(self.perms.HasPerm('Cc', 111L, self.proj)) |
| 106 self.assertTrue(self.perms.HasPerm('CC', 111L, self.proj)) |
| 107 self.assertFalse(self.perms.HasPerm('Z', 111L, self.proj)) |
| 108 |
| 109 self.assertFalse(self.perms.HasPerm('d', 222L, self.proj)) |
| 110 self.assertFalse(self.perms.HasPerm('D', 222L, self.proj)) |
| 111 |
| 112 # Only current members can have extra permissions |
| 113 self.proj.contributor_ids = [] |
| 114 self.assertFalse(self.perms.HasPerm('d', 111L, self.proj)) |
| 115 |
| 116 # TODO(jrobbins): also test consider_restrictions=False and |
| 117 # restriction labels directly in this class. |
| 118 |
| 119 def testHasPerm_GrantedPerms(self): |
| 120 self.assertTrue(self.perms.CanUsePerm( |
| 121 'A', {111L}, self.proj, [], granted_perms=['z'])) |
| 122 self.assertTrue(self.perms.CanUsePerm( |
| 123 'a', {111L}, self.proj, [], granted_perms=['z'])) |
| 124 self.assertTrue(self.perms.CanUsePerm( |
| 125 'a', {111L}, self.proj, [], granted_perms=['a'])) |
| 126 self.assertTrue(self.perms.CanUsePerm( |
| 127 'Z', {111L}, self.proj, [], granted_perms=['y', 'z'])) |
| 128 self.assertTrue(self.perms.CanUsePerm( |
| 129 'z', {111L}, self.proj, [], granted_perms=['y', 'z'])) |
| 130 self.assertFalse(self.perms.CanUsePerm( |
| 131 'z', {111L}, self.proj, [], granted_perms=['y'])) |
| 132 |
| 133 def testDebugString(self): |
| 134 self.assertEqual('PermissionSet()', |
| 135 permissions.PermissionSet([]).DebugString()) |
| 136 self.assertEqual('PermissionSet(a)', |
| 137 permissions.PermissionSet(['A']).DebugString()) |
| 138 self.assertEqual('PermissionSet(a, b, cc)', self.perms.DebugString()) |
| 139 |
| 140 def testRepr(self): |
| 141 self.assertEqual('PermissionSet(frozenset([]))', |
| 142 permissions.PermissionSet([]).__repr__()) |
| 143 self.assertEqual('PermissionSet(frozenset([\'a\']))', |
| 144 permissions.PermissionSet(['A']).__repr__()) |
| 145 |
| 146 |
| 147 class PermissionsTest(unittest.TestCase): |
| 148 |
| 149 NOW = 1277762224 # Any timestamp will do, we only compare it to itself +/- 1 |
| 150 COMMITTER_USER_ID = 111L |
| 151 OWNER_USER_ID = 222L |
| 152 CONTRIB_USER_ID = 333L |
| 153 SITE_ADMIN_USER_ID = 444L |
| 154 |
| 155 def MakeProject(self, project_name, state, add_members=True, access=None): |
| 156 args = dict(project_name=project_name, state=state) |
| 157 if add_members: |
| 158 args.update(owner_ids=[self.OWNER_USER_ID], |
| 159 committer_ids=[self.COMMITTER_USER_ID], |
| 160 contributor_ids=[self.CONTRIB_USER_ID]) |
| 161 |
| 162 if access: |
| 163 args.update(access=access) |
| 164 |
| 165 return fake.Project(**args) |
| 166 |
| 167 def setUp(self): |
| 168 self.live_project = self.MakeProject('live', project_pb2.ProjectState.LIVE) |
| 169 self.archived_project = self.MakeProject( |
| 170 'archived', project_pb2.ProjectState.ARCHIVED) |
| 171 self.other_live_project = self.MakeProject( |
| 172 'other_live', project_pb2.ProjectState.LIVE, add_members=False) |
| 173 self.members_only_project = self.MakeProject( |
| 174 's3kr3t', project_pb2.ProjectState.LIVE, |
| 175 access=project_pb2.ProjectAccess.MEMBERS_ONLY) |
| 176 |
| 177 self.nonmember = user_pb2.User() |
| 178 self.member = user_pb2.User() |
| 179 self.owner = user_pb2.User() |
| 180 self.contrib = user_pb2.User() |
| 181 self.site_admin = user_pb2.User() |
| 182 self.site_admin.is_site_admin = True |
| 183 self.borg_user = user_pb2.User(email=settings.borg_service_account) |
| 184 |
| 185 self.normal_artifact = tracker_pb2.Issue() |
| 186 self.normal_artifact.labels.extend(['hot', 'Key-Value']) |
| 187 self.normal_artifact.reporter_id = 111L |
| 188 |
| 189 # Two PermissionSets w/ permissions outside of any project. |
| 190 self.normal_user_perms = permissions.GetPermissions( |
| 191 None, {111L}, None) |
| 192 self.admin_perms = permissions.PermissionSet( |
| 193 [permissions.ADMINISTER_SITE, |
| 194 permissions.CREATE_PROJECT]) |
| 195 |
| 196 self.mox = mox.Mox() |
| 197 |
| 198 def tearDown(self): |
| 199 self.mox.UnsetStubs() |
| 200 |
| 201 def testGetPermissions_Admin(self): |
| 202 self.assertEqual( |
| 203 permissions.ADMIN_PERMISSIONSET, |
| 204 permissions.GetPermissions(self.site_admin, None, None)) |
| 205 |
| 206 def testGetPermissions_BorgServiceAccount(self): |
| 207 self.assertEqual( |
| 208 permissions.GROUP_IMPORT_BORG_PERMISSIONSET, |
| 209 permissions.GetPermissions(self.borg_user, None, None)) |
| 210 |
| 211 def CheckPermissions(self, perms, expected_list): |
| 212 expect_view, expect_commit, expect_edit_project = expected_list |
| 213 self.assertEqual( |
| 214 expect_view, perms.HasPerm(permissions.VIEW, None, None)) |
| 215 self.assertEqual( |
| 216 expect_commit, perms.HasPerm(permissions.COMMIT, None, None)) |
| 217 self.assertEqual( |
| 218 expect_edit_project, |
| 219 perms.HasPerm(permissions.EDIT_PROJECT, None, None)) |
| 220 |
| 221 def testAnonPermissions(self): |
| 222 perms = permissions.GetPermissions(None, set(), self.live_project) |
| 223 self.CheckPermissions(perms, [True, False, False]) |
| 224 |
| 225 perms = permissions.GetPermissions(None, set(), self.members_only_project) |
| 226 self.CheckPermissions(perms, [False, False, False]) |
| 227 |
| 228 def testNonmemberPermissions(self): |
| 229 perms = permissions.GetPermissions( |
| 230 self.nonmember, {123}, self.live_project) |
| 231 self.CheckPermissions(perms, [True, False, False]) |
| 232 |
| 233 perms = permissions.GetPermissions( |
| 234 self.nonmember, {123}, self.members_only_project) |
| 235 self.CheckPermissions(perms, [False, False, False]) |
| 236 |
| 237 def testMemberPermissions(self): |
| 238 perms = permissions.GetPermissions( |
| 239 self.member, {self.COMMITTER_USER_ID}, self.live_project) |
| 240 self.CheckPermissions(perms, [True, True, False]) |
| 241 |
| 242 perms = permissions.GetPermissions( |
| 243 self.member, {self.COMMITTER_USER_ID}, self.other_live_project) |
| 244 self.CheckPermissions(perms, [True, False, False]) |
| 245 |
| 246 perms = permissions.GetPermissions( |
| 247 self.member, {self.COMMITTER_USER_ID}, self.members_only_project) |
| 248 self.CheckPermissions(perms, [True, True, False]) |
| 249 |
| 250 def testOwnerPermissions(self): |
| 251 perms = permissions.GetPermissions( |
| 252 self.owner, {self.OWNER_USER_ID}, self.live_project) |
| 253 self.CheckPermissions(perms, [True, True, True]) |
| 254 |
| 255 perms = permissions.GetPermissions( |
| 256 self.owner, {self.OWNER_USER_ID}, self.other_live_project) |
| 257 self.CheckPermissions(perms, [True, False, False]) |
| 258 |
| 259 perms = permissions.GetPermissions( |
| 260 self.owner, {self.OWNER_USER_ID}, self.members_only_project) |
| 261 self.CheckPermissions(perms, [True, True, True]) |
| 262 |
| 263 def testContributorPermissions(self): |
| 264 perms = permissions.GetPermissions( |
| 265 self.contrib, {self.CONTRIB_USER_ID}, self.live_project) |
| 266 self.CheckPermissions(perms, [True, False, False]) |
| 267 |
| 268 perms = permissions.GetPermissions( |
| 269 self.contrib, {self.CONTRIB_USER_ID}, self.other_live_project) |
| 270 self.CheckPermissions(perms, [True, False, False]) |
| 271 |
| 272 perms = permissions.GetPermissions( |
| 273 self.contrib, {self.CONTRIB_USER_ID}, self.members_only_project) |
| 274 self.CheckPermissions(perms, [True, False, False]) |
| 275 |
| 276 def testLookupPermset_ExactMatch(self): |
| 277 self.assertEqual( |
| 278 permissions.USER_PERMISSIONSET, |
| 279 permissions._LookupPermset( |
| 280 permissions.USER_ROLE, project_pb2.ProjectState.LIVE, |
| 281 project_pb2.ProjectAccess.ANYONE)) |
| 282 |
| 283 def testLookupPermset_WildcardAccess(self): |
| 284 self.assertEqual( |
| 285 permissions.OWNER_ACTIVE_PERMISSIONSET, |
| 286 permissions._LookupPermset( |
| 287 permissions.OWNER_ROLE, project_pb2.ProjectState.LIVE, |
| 288 project_pb2.ProjectAccess.MEMBERS_ONLY)) |
| 289 |
| 290 def testGetPermissionKey_AnonUser(self): |
| 291 self.assertEqual( |
| 292 (permissions.ANON_ROLE, permissions.UNDEFINED_STATUS, |
| 293 permissions.UNDEFINED_ACCESS), |
| 294 permissions._GetPermissionKey(None, None)) |
| 295 self.assertEqual( |
| 296 (permissions.ANON_ROLE, project_pb2.ProjectState.LIVE, |
| 297 project_pb2.ProjectAccess.ANYONE), |
| 298 permissions._GetPermissionKey(None, self.live_project)) |
| 299 |
| 300 def testGetPermissionKey_ExpiredProject(self): |
| 301 self.archived_project.delete_time = self.NOW |
| 302 # In an expired project, the user's committe role does not count. |
| 303 self.assertEqual( |
| 304 (permissions.USER_ROLE, project_pb2.ProjectState.ARCHIVED, |
| 305 project_pb2.ProjectAccess.ANYONE), |
| 306 permissions._GetPermissionKey( |
| 307 self.COMMITTER_USER_ID, self.archived_project, |
| 308 expired_before=self.NOW + 1)) |
| 309 # If not expired yet, the user's committe role still counts. |
| 310 self.assertEqual( |
| 311 (permissions.COMMITTER_ROLE, project_pb2.ProjectState.ARCHIVED, |
| 312 project_pb2.ProjectAccess.ANYONE), |
| 313 permissions._GetPermissionKey( |
| 314 self.COMMITTER_USER_ID, self.archived_project, |
| 315 expired_before=self.NOW - 1)) |
| 316 |
| 317 def testGetPermissionKey_DefinedRoles(self): |
| 318 self.assertEqual( |
| 319 (permissions.OWNER_ROLE, project_pb2.ProjectState.LIVE, |
| 320 project_pb2.ProjectAccess.ANYONE), |
| 321 permissions._GetPermissionKey( |
| 322 self.OWNER_USER_ID, self.live_project)) |
| 323 self.assertEqual( |
| 324 (permissions.COMMITTER_ROLE, project_pb2.ProjectState.LIVE, |
| 325 project_pb2.ProjectAccess.ANYONE), |
| 326 permissions._GetPermissionKey( |
| 327 self.COMMITTER_USER_ID, self.live_project)) |
| 328 self.assertEqual( |
| 329 (permissions.CONTRIBUTOR_ROLE, project_pb2.ProjectState.LIVE, |
| 330 project_pb2.ProjectAccess.ANYONE), |
| 331 permissions._GetPermissionKey( |
| 332 self.CONTRIB_USER_ID, self.live_project)) |
| 333 |
| 334 def testGetPermissionKey_Nonmember(self): |
| 335 self.assertEqual( |
| 336 (permissions.USER_ROLE, project_pb2.ProjectState.LIVE, |
| 337 project_pb2.ProjectAccess.ANYONE), |
| 338 permissions._GetPermissionKey( |
| 339 999L, self.live_project)) |
| 340 |
| 341 def testPermissionsImmutable(self): |
| 342 self.assertTrue(isinstance( |
| 343 permissions.EMPTY_PERMISSIONSET.perm_names, frozenset)) |
| 344 self.assertTrue(isinstance( |
| 345 permissions.READ_ONLY_PERMISSIONSET.perm_names, frozenset)) |
| 346 self.assertTrue(isinstance( |
| 347 permissions.COMMITTER_ACTIVE_PERMISSIONSET.perm_names, frozenset)) |
| 348 self.assertTrue(isinstance( |
| 349 permissions.OWNER_ACTIVE_PERMISSIONSET.perm_names, frozenset)) |
| 350 |
| 351 def testGetExtraPerms(self): |
| 352 project = project_pb2.Project() |
| 353 project.committer_ids.append(222L) |
| 354 project.extra_perms.append(project_pb2.Project.ExtraPerms( |
| 355 member_id=222L, perms=['a', 'b', 'c'])) |
| 356 # User 1 is a former member with left-over extra perms that don't count. |
| 357 project.extra_perms.append(project_pb2.Project.ExtraPerms( |
| 358 member_id=111L, perms=['a', 'b', 'c'])) |
| 359 |
| 360 self.assertListEqual( |
| 361 [], |
| 362 permissions.GetExtraPerms(project, 111L)) |
| 363 self.assertListEqual( |
| 364 ['a', 'b', 'c'], |
| 365 permissions.GetExtraPerms(project, 222L)) |
| 366 self.assertListEqual( |
| 367 [], |
| 368 permissions.GetExtraPerms(project, 333L)) |
| 369 |
| 370 def testAnonUsersCannotDelete(self): |
| 371 perms = permissions.PermissionSet([permissions.DELETE_ANY]) |
| 372 # No logged in user, no perms specfied. |
| 373 self.assertFalse(permissions.CanDelete( |
| 374 framework_constants.NO_USER_SPECIFIED, set(), None, 0, 0, None, [])) |
| 375 # No logged in user, even with perms from somewhere. |
| 376 self.assertFalse(permissions.CanDelete( |
| 377 framework_constants.NO_USER_SPECIFIED, set(), perms, 0, 0, None, [])) |
| 378 # No logged in user, even if artifact was already deleted. |
| 379 self.assertFalse(permissions.CanDelete( |
| 380 framework_constants.NO_USER_SPECIFIED, set(), perms, |
| 381 111L, 111L, None, [])) |
| 382 # No logged in user, even if artifact was already deleted by project owner. |
| 383 self.assertFalse(permissions.CanDelete( |
| 384 framework_constants.NO_USER_SPECIFIED, set(), perms, |
| 385 111L, 222L, None, [])) |
| 386 |
| 387 def testProjectOwnerCanDeleteAnyArtifact(self): |
| 388 perms = permissions.PermissionSet([permissions.DELETE_ANY]) |
| 389 # No artifact owner, and not already deleted. |
| 390 self.assertTrue(permissions.CanDelete( |
| 391 111L, {111L}, perms, 0, 0, None, [])) |
| 392 # I already deleted, can undelete. |
| 393 self.assertTrue(permissions.CanDelete( |
| 394 111L, {111L}, perms, 111L, 0, None, [])) |
| 395 # I can delete my own thing. |
| 396 self.assertTrue(permissions.CanDelete( |
| 397 111L, {111L}, perms, 0, 111L, None, [])) |
| 398 # I can also delete another user's artifacts, because I have DELETE_ANY. |
| 399 self.assertTrue(permissions.CanDelete( |
| 400 111L, {111L}, perms, 0, 222L, None, [])) |
| 401 # I can always undelete, even if another PO deleted it. |
| 402 self.assertTrue(permissions.CanDelete( |
| 403 111L, {111L}, perms, 333L, 222L, None, [])) |
| 404 |
| 405 def testUserCanDeleteTheirOwnStuff(self): |
| 406 perms = permissions.PermissionSet([permissions.DELETE_OWN]) |
| 407 # I can delete/withdraw my artifact or comment. |
| 408 self.assertTrue(permissions.CanDelete( |
| 409 111L, {111L}, perms, 0, 111L, None, [])) |
| 410 # I can undelete what I deleted. |
| 411 self.assertTrue(permissions.CanDelete( |
| 412 111L, {111L}, perms, 111L, 111L, None, [])) |
| 413 # I cannot undelete if someone else deleted my spam. |
| 414 self.assertFalse(permissions.CanDelete( |
| 415 111L, {111L}, perms, 222L, 111L, None, [])) |
| 416 # I cannot delete other people's stuff. |
| 417 self.assertFalse(permissions.CanDelete( |
| 418 111L, {111L}, perms, 0, 222L, None, [])) |
| 419 # I cannot undelete what other people withdrew. |
| 420 self.assertFalse(permissions.CanDelete( |
| 421 111L, {111L}, perms, 222L, 222L, None, [])) |
| 422 |
| 423 def testCanViewNormalArifact(self): |
| 424 # Anyone can view a non-restricted artifact. |
| 425 self.assertTrue(permissions.CanView( |
| 426 {111L}, permissions.READ_ONLY_PERMISSIONSET, |
| 427 self.live_project, [])) |
| 428 |
| 429 def testCanCreateProject_NoPerms(self): |
| 430 """Signed out users cannot create projects.""" |
| 431 self.assertFalse(permissions.CanCreateProject( |
| 432 permissions.EMPTY_PERMISSIONSET)) |
| 433 |
| 434 self.assertFalse(permissions.CanCreateProject( |
| 435 permissions.READ_ONLY_PERMISSIONSET)) |
| 436 |
| 437 def testCanCreateProject_Admin(self): |
| 438 """Site admins can create projects.""" |
| 439 self.assertTrue(permissions.CanCreateProject( |
| 440 permissions.ADMIN_PERMISSIONSET)) |
| 441 |
| 442 def testCanCreateProject_RegularUser(self): |
| 443 """Signed in non-admins can create a project if settings allow ANYONE.""" |
| 444 try: |
| 445 orig_restriction = settings.project_creation_restriction |
| 446 ANYONE = site_pb2.UserTypeRestriction.ANYONE |
| 447 ADMIN_ONLY = site_pb2.UserTypeRestriction.ADMIN_ONLY |
| 448 NO_ONE = site_pb2.UserTypeRestriction.NO_ONE |
| 449 perms = permissions.PermissionSet([permissions.CREATE_PROJECT]) |
| 450 |
| 451 settings.project_creation_restriction = ANYONE |
| 452 self.assertTrue(permissions.CanCreateProject(perms)) |
| 453 |
| 454 settings.project_creation_restriction = ADMIN_ONLY |
| 455 self.assertFalse(permissions.CanCreateProject(perms)) |
| 456 |
| 457 settings.project_creation_restriction = NO_ONE |
| 458 self.assertFalse(permissions.CanCreateProject(perms)) |
| 459 self.assertFalse(permissions.CanCreateProject( |
| 460 permissions.ADMIN_PERMISSIONSET)) |
| 461 finally: |
| 462 settings.project_creation_restriction = orig_restriction |
| 463 |
| 464 def testCanCreateGroup_AnyoneWithCreateGroup(self): |
| 465 orig_setting = settings.group_creation_restriction |
| 466 try: |
| 467 settings.group_creation_restriction = site_pb2.UserTypeRestriction.ANYONE |
| 468 self.assertTrue(permissions.CanCreateGroup( |
| 469 permissions.PermissionSet([permissions.CREATE_GROUP]))) |
| 470 self.assertFalse(permissions.CanCreateGroup( |
| 471 permissions.PermissionSet([]))) |
| 472 finally: |
| 473 settings.group_creation_restriction = orig_setting |
| 474 |
| 475 def testCanCreateGroup_AdminOnly(self): |
| 476 orig_setting = settings.group_creation_restriction |
| 477 try: |
| 478 ADMIN_ONLY = site_pb2.UserTypeRestriction.ADMIN_ONLY |
| 479 settings.group_creation_restriction = ADMIN_ONLY |
| 480 self.assertTrue(permissions.CanCreateGroup( |
| 481 permissions.PermissionSet([permissions.ADMINISTER_SITE]))) |
| 482 self.assertFalse(permissions.CanCreateGroup( |
| 483 permissions.PermissionSet([permissions.CREATE_GROUP]))) |
| 484 self.assertFalse(permissions.CanCreateGroup( |
| 485 permissions.PermissionSet([]))) |
| 486 finally: |
| 487 settings.group_creation_restriction = orig_setting |
| 488 |
| 489 def testCanCreateGroup_UnspecifiedSetting(self): |
| 490 orig_setting = settings.group_creation_restriction |
| 491 try: |
| 492 settings.group_creation_restriction = None |
| 493 self.assertFalse(permissions.CanCreateGroup( |
| 494 permissions.PermissionSet([permissions.ADMINISTER_SITE]))) |
| 495 self.assertFalse(permissions.CanCreateGroup( |
| 496 permissions.PermissionSet([permissions.CREATE_GROUP]))) |
| 497 self.assertFalse(permissions.CanCreateGroup( |
| 498 permissions.PermissionSet([]))) |
| 499 finally: |
| 500 settings.group_creation_restriction = orig_setting |
| 501 |
| 502 def testCanEditGroup_HasPerm(self): |
| 503 self.assertTrue(permissions.CanEditGroup( |
| 504 permissions.PermissionSet([permissions.EDIT_GROUP]), None, None)) |
| 505 |
| 506 def testCanEditGroup_IsOwner(self): |
| 507 self.assertTrue(permissions.CanEditGroup( |
| 508 permissions.PermissionSet([]), {111L}, {111L})) |
| 509 |
| 510 def testCanEditGroup_Otherwise(self): |
| 511 self.assertFalse(permissions.CanEditGroup( |
| 512 permissions.PermissionSet([]), {111L}, {222L})) |
| 513 |
| 514 def testCanViewGroup_HasPerm(self): |
| 515 self.assertTrue(permissions.CanViewGroup( |
| 516 permissions.PermissionSet([permissions.VIEW_GROUP]), |
| 517 None, None, None, None, None)) |
| 518 |
| 519 def testCanViewGroup_IsMemberOfFriendProject(self): |
| 520 group_settings = usergroup_pb2.MakeSettings('owners', friend_projects=[890]) |
| 521 self.assertFalse(permissions.CanViewGroup( |
| 522 permissions.PermissionSet([]), |
| 523 {111L}, group_settings, {222L}, {333L}, {789})) |
| 524 self.assertTrue(permissions.CanViewGroup( |
| 525 permissions.PermissionSet([]), |
| 526 {111L}, group_settings, {222L}, {333L}, {789, 890})) |
| 527 |
| 528 def testCanViewGroup_VisibleToOwner(self): |
| 529 group_settings = usergroup_pb2.MakeSettings('owners') |
| 530 self.assertFalse(permissions.CanViewGroup( |
| 531 permissions.PermissionSet([]), |
| 532 {111L}, group_settings, {222L}, {333L}, {789})) |
| 533 self.assertFalse(permissions.CanViewGroup( |
| 534 permissions.PermissionSet([]), |
| 535 {222L}, group_settings, {222L}, {333L}, {789})) |
| 536 self.assertTrue(permissions.CanViewGroup( |
| 537 permissions.PermissionSet([]), |
| 538 {333L}, group_settings, {222L}, {333L}, {789})) |
| 539 |
| 540 def testCanViewGroup_IsVisibleToMember(self): |
| 541 group_settings = usergroup_pb2.MakeSettings('members') |
| 542 self.assertFalse(permissions.CanViewGroup( |
| 543 permissions.PermissionSet([]), |
| 544 {111L}, group_settings, {222L}, {333L}, {789})) |
| 545 self.assertTrue(permissions.CanViewGroup( |
| 546 permissions.PermissionSet([]), |
| 547 {222L}, group_settings, {222L}, {333L}, {789})) |
| 548 self.assertTrue(permissions.CanViewGroup( |
| 549 permissions.PermissionSet([]), |
| 550 {333L}, group_settings, {222L}, {333L}, {789})) |
| 551 |
| 552 def testCanViewGroup_AnyoneCanView(self): |
| 553 group_settings = usergroup_pb2.MakeSettings('anyone') |
| 554 self.assertTrue(permissions.CanViewGroup( |
| 555 permissions.PermissionSet([]), |
| 556 {111L}, group_settings, {222L}, {333L}, {789})) |
| 557 |
| 558 def testIsBanned_AnonUser(self): |
| 559 user_view = framework_views.UserView(None, None, True) |
| 560 self.assertFalse(permissions.IsBanned(None, user_view)) |
| 561 |
| 562 def testIsBanned_NormalUser(self): |
| 563 user = user_pb2.User() |
| 564 user_view = framework_views.UserView(None, None, True) |
| 565 self.assertFalse(permissions.IsBanned(user, user_view)) |
| 566 |
| 567 def testIsBanned_BannedUser(self): |
| 568 user = user_pb2.User() |
| 569 user.banned = 'spammer' |
| 570 user_view = framework_views.UserView(None, None, True) |
| 571 self.assertTrue(permissions.IsBanned(user, user_view)) |
| 572 |
| 573 def testIsBanned_BadDomainUser(self): |
| 574 settings.banned_user_domains = ['spammer.com', 'phisher.com'] |
| 575 user = user_pb2.User() |
| 576 user_view = framework_views.UserView(None, None, True) |
| 577 user_view.domain = 'spammer.com' |
| 578 self.assertTrue(permissions.IsBanned(user, user_view)) |
| 579 |
| 580 def testGetCustomPermissions(self): |
| 581 project = project_pb2.Project() |
| 582 self.assertListEqual([], permissions.GetCustomPermissions(project)) |
| 583 |
| 584 project.extra_perms.append(project_pb2.Project.ExtraPerms( |
| 585 perms=['Core', 'Elite', 'Gold'])) |
| 586 self.assertListEqual(['Core', 'Elite', 'Gold'], |
| 587 permissions.GetCustomPermissions(project)) |
| 588 |
| 589 project.extra_perms.append(project_pb2.Project.ExtraPerms( |
| 590 perms=['Silver', 'Gold', 'Bronze'])) |
| 591 self.assertListEqual(['Bronze', 'Core', 'Elite', 'Gold', 'Silver'], |
| 592 permissions.GetCustomPermissions(project)) |
| 593 |
| 594 def testUserCanViewProject(self): |
| 595 self.mox.StubOutWithMock(time, 'time') |
| 596 for _ in range(8): |
| 597 time.time().AndReturn(self.NOW) |
| 598 self.mox.ReplayAll() |
| 599 |
| 600 self.assertTrue(permissions.UserCanViewProject( |
| 601 self.member, {self.COMMITTER_USER_ID}, self.live_project)) |
| 602 self.assertTrue(permissions.UserCanViewProject( |
| 603 None, None, self.live_project)) |
| 604 |
| 605 self.archived_project.delete_time = self.NOW + 1 |
| 606 self.assertFalse(permissions.UserCanViewProject( |
| 607 None, None, self.archived_project)) |
| 608 self.assertTrue(permissions.UserCanViewProject( |
| 609 self.owner, {self.OWNER_USER_ID}, self.archived_project)) |
| 610 self.assertTrue(permissions.UserCanViewProject( |
| 611 self.site_admin, {self.SITE_ADMIN_USER_ID}, |
| 612 self.archived_project)) |
| 613 |
| 614 self.archived_project.delete_time = self.NOW - 1 |
| 615 self.assertFalse(permissions.UserCanViewProject( |
| 616 None, None, self.archived_project)) |
| 617 self.assertFalse(permissions.UserCanViewProject( |
| 618 self.owner, {self.OWNER_USER_ID}, self.archived_project)) |
| 619 self.assertTrue(permissions.UserCanViewProject( |
| 620 self.site_admin, {self.SITE_ADMIN_USER_ID}, |
| 621 self.archived_project)) |
| 622 |
| 623 self.mox.VerifyAll() |
| 624 |
| 625 def CheckExpired(self, state, expected_to_be_reapable): |
| 626 proj = project_pb2.Project() |
| 627 proj.state = state |
| 628 proj.delete_time = self.NOW + 1 |
| 629 self.assertFalse(permissions.IsExpired(proj)) |
| 630 |
| 631 proj.delete_time = self.NOW - 1 |
| 632 self.assertEqual(expected_to_be_reapable, permissions.IsExpired(proj)) |
| 633 |
| 634 proj.delete_time = self.NOW - 1 |
| 635 self.assertFalse(permissions.IsExpired(proj, expired_before=self.NOW - 2)) |
| 636 |
| 637 def testIsExpired_Live(self): |
| 638 self.CheckExpired(project_pb2.ProjectState.LIVE, False) |
| 639 |
| 640 def testIsExpired_Archived(self): |
| 641 self.mox.StubOutWithMock(time, 'time') |
| 642 for _ in range(2): |
| 643 time.time().AndReturn(self.NOW) |
| 644 self.mox.ReplayAll() |
| 645 |
| 646 self.CheckExpired(project_pb2.ProjectState.ARCHIVED, True) |
| 647 |
| 648 self.mox.VerifyAll() |
| 649 |
| 650 |
| 651 class PermissionsCheckTest(unittest.TestCase): |
| 652 |
| 653 def setUp(self): |
| 654 self.perms = permissions.PermissionSet(['a', 'b', 'c']) |
| 655 |
| 656 self.proj = project_pb2.Project() |
| 657 self.proj.committer_ids.append(111L) |
| 658 self.proj.extra_perms.append(project_pb2.Project.ExtraPerms( |
| 659 member_id=111L, perms=['d'])) |
| 660 |
| 661 # Note: z is an example of a perm that the user does not have. |
| 662 # Note: q is an example of an irrelevant perm that the user does not have. |
| 663 |
| 664 def DoCanUsePerm(self, perm, project='default', user_id=None, restrict=''): |
| 665 """Wrapper function to call CanUsePerm().""" |
| 666 if project == 'default': |
| 667 project = self.proj |
| 668 return self.perms.CanUsePerm( |
| 669 perm, {user_id or 111L}, project, restrict.split()) |
| 670 |
| 671 def testHasPermNoRestrictions(self): |
| 672 self.assertTrue(self.DoCanUsePerm('a')) |
| 673 self.assertTrue(self.DoCanUsePerm('A')) |
| 674 self.assertFalse(self.DoCanUsePerm('z')) |
| 675 self.assertTrue(self.DoCanUsePerm('d')) |
| 676 self.assertFalse(self.DoCanUsePerm('d', user_id=222L)) |
| 677 self.assertFalse(self.DoCanUsePerm('d', project=project_pb2.Project())) |
| 678 |
| 679 def testHasPermOperationRestrictions(self): |
| 680 self.assertTrue(self.DoCanUsePerm('a', restrict='Restrict-a-b')) |
| 681 self.assertTrue(self.DoCanUsePerm('a', restrict='Restrict-b-z')) |
| 682 self.assertTrue(self.DoCanUsePerm('a', restrict='Restrict-a-d')) |
| 683 self.assertTrue(self.DoCanUsePerm('d', restrict='Restrict-d-a')) |
| 684 self.assertTrue(self.DoCanUsePerm( |
| 685 'd', restrict='Restrict-q-z Restrict-q-d Restrict-d-a')) |
| 686 |
| 687 self.assertFalse(self.DoCanUsePerm('a', restrict='Restrict-a-z')) |
| 688 self.assertFalse(self.DoCanUsePerm('d', restrict='Restrict-d-z')) |
| 689 self.assertFalse(self.DoCanUsePerm( |
| 690 'd', restrict='Restrict-d-a Restrict-d-z')) |
| 691 |
| 692 def testHasPermOutsideProjectScope(self): |
| 693 self.assertTrue(self.DoCanUsePerm('a', project=None)) |
| 694 self.assertTrue(self.DoCanUsePerm( |
| 695 'a', project=None, restrict='Restrict-a-c')) |
| 696 self.assertTrue(self.DoCanUsePerm( |
| 697 'a', project=None, restrict='Restrict-q-z')) |
| 698 |
| 699 self.assertFalse(self.DoCanUsePerm('z', project=None)) |
| 700 self.assertFalse(self.DoCanUsePerm( |
| 701 'a', project=None, restrict='Restrict-a-d')) |
| 702 |
| 703 |
| 704 class CanViewProjectContributorListTest(unittest.TestCase): |
| 705 |
| 706 def testCanViewProjectContributorList_NoProject(self): |
| 707 mr = testing_helpers.MakeMonorailRequest(path='/') |
| 708 self.assertFalse(permissions.CanViewContributorList(mr)) |
| 709 |
| 710 def testCanViewProjectContributorList_NormalProject(self): |
| 711 project = project_pb2.Project() |
| 712 mr = testing_helpers.MakeMonorailRequest( |
| 713 path='/p/proj/', project=project) |
| 714 self.assertTrue(permissions.CanViewContributorList(mr)) |
| 715 |
| 716 def testCanViewProjectContributorList_ProjectWithOptionSet(self): |
| 717 project = project_pb2.Project() |
| 718 project.only_owners_see_contributors = True |
| 719 |
| 720 for perms in [permissions.READ_ONLY_PERMISSIONSET, |
| 721 permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET, |
| 722 permissions.CONTRIBUTOR_INACTIVE_PERMISSIONSET]: |
| 723 mr = testing_helpers.MakeMonorailRequest( |
| 724 path='/p/proj/', project=project, perms=perms) |
| 725 self.assertFalse(permissions.CanViewContributorList(mr)) |
| 726 |
| 727 for perms in [permissions.COMMITTER_ACTIVE_PERMISSIONSET, |
| 728 permissions.COMMITTER_INACTIVE_PERMISSIONSET, |
| 729 permissions.OWNER_ACTIVE_PERMISSIONSET, |
| 730 permissions.OWNER_INACTIVE_PERMISSIONSET, |
| 731 permissions.ADMIN_PERMISSIONSET]: |
| 732 mr = testing_helpers.MakeMonorailRequest( |
| 733 path='/p/proj/', project=project, perms=perms) |
| 734 self.assertTrue(permissions.CanViewContributorList(mr)) |
| 735 |
| 736 |
| 737 class ShouldCheckForAbandonmentTest(unittest.TestCase): |
| 738 |
| 739 def setUp(self): |
| 740 self.mr = testing_helpers.Blank( |
| 741 project=project_pb2.Project(), |
| 742 auth=monorailrequest.AuthData()) |
| 743 |
| 744 def testOwner(self): |
| 745 self.mr.auth.effective_ids = {111L} |
| 746 self.mr.perms = permissions.OWNER_ACTIVE_PERMISSIONSET |
| 747 self.assertTrue(permissions.ShouldCheckForAbandonment(self.mr)) |
| 748 |
| 749 def testNonOwner(self): |
| 750 self.mr.auth.effective_ids = {222L} |
| 751 self.mr.perms = permissions.COMMITTER_ACTIVE_PERMISSIONSET |
| 752 self.assertFalse(permissions.ShouldCheckForAbandonment(self.mr)) |
| 753 self.mr.perms = permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET |
| 754 self.assertFalse(permissions.ShouldCheckForAbandonment(self.mr)) |
| 755 self.mr.perms = permissions.USER_PERMISSIONSET |
| 756 self.assertFalse(permissions.ShouldCheckForAbandonment(self.mr)) |
| 757 self.mr.perms = permissions.EMPTY_PERMISSIONSET |
| 758 self.assertFalse(permissions.ShouldCheckForAbandonment(self.mr)) |
| 759 |
| 760 def testSiteAdmin(self): |
| 761 self.mr.auth.effective_ids = {111L} |
| 762 self.mr.perms = permissions.ADMIN_PERMISSIONSET |
| 763 self.assertFalse(permissions.ShouldCheckForAbandonment(self.mr)) |
| 764 |
| 765 |
| 766 class RestrictionLabelsTest(unittest.TestCase): |
| 767 |
| 768 ORIG_SUMMARY = 'this is the orginal summary' |
| 769 ORIG_LABELS = ['one', 'two'] |
| 770 |
| 771 def testGetRestrictions_NoIssue(self): |
| 772 self.assertEqual([], permissions.GetRestrictions(None)) |
| 773 |
| 774 def testGetRestrictions(self): |
| 775 art = fake.MakeTestIssue( |
| 776 789, 1, self.ORIG_SUMMARY, 'New', 0L, labels=self.ORIG_LABELS) |
| 777 self.assertEquals([], permissions.GetRestrictions(art)) |
| 778 |
| 779 art = fake.MakeTestIssue( |
| 780 789, 1, self.ORIG_SUMMARY, 'New', 0L, |
| 781 labels=['Restrict-MissingThirdPart', 'Hot']) |
| 782 self.assertEquals([], permissions.GetRestrictions(art)) |
| 783 |
| 784 art = fake.MakeTestIssue( |
| 785 789, 1, self.ORIG_SUMMARY, 'New', 0L, |
| 786 labels=['Restrict-View-Core', 'Hot']) |
| 787 self.assertEquals(['restrict-view-core'], permissions.GetRestrictions(art)) |
| 788 |
| 789 art = fake.MakeTestIssue( |
| 790 789, 1, self.ORIG_SUMMARY, 'New', 0L, |
| 791 labels=['Restrict-View-Core', 'Hot'], |
| 792 derived_labels=['Color-Red', 'Restrict-EditIssue-GoldMembers']) |
| 793 self.assertEquals( |
| 794 ['restrict-view-core', 'restrict-editissue-goldmembers'], |
| 795 permissions.GetRestrictions(art)) |
| 796 |
| 797 art = fake.MakeTestIssue( |
| 798 789, 1, self.ORIG_SUMMARY, 'New', 0L, |
| 799 labels=['restrict-view-core', 'hot'], |
| 800 derived_labels=['Color-Red', 'RESTRICT-EDITISSUE-GOLDMEMBERS']) |
| 801 self.assertEquals( |
| 802 ['restrict-view-core', 'restrict-editissue-goldmembers'], |
| 803 permissions.GetRestrictions(art)) |
| 804 |
| 805 |
| 806 REPORTER_ID = 111L |
| 807 OWNER_ID = 222L |
| 808 CC_ID = 333L |
| 809 OTHER_ID = 444L |
| 810 |
| 811 |
| 812 class IssuePermissionsTest(unittest.TestCase): |
| 813 |
| 814 REGULAR_ISSUE = tracker_pb2.Issue() |
| 815 REGULAR_ISSUE.reporter_id = REPORTER_ID |
| 816 |
| 817 DELETED_ISSUE = tracker_pb2.Issue() |
| 818 DELETED_ISSUE.deleted = True |
| 819 DELETED_ISSUE.reporter_id = REPORTER_ID |
| 820 |
| 821 RESTRICTED_ISSUE = tracker_pb2.Issue() |
| 822 RESTRICTED_ISSUE.reporter_id = REPORTER_ID |
| 823 RESTRICTED_ISSUE.owner_id = OWNER_ID |
| 824 RESTRICTED_ISSUE.cc_ids.append(CC_ID) |
| 825 RESTRICTED_ISSUE.labels.append('Restrict-View-Commit') |
| 826 |
| 827 RESTRICTED_ISSUE2 = tracker_pb2.Issue() |
| 828 RESTRICTED_ISSUE2.reporter_id = REPORTER_ID |
| 829 # RESTRICTED_ISSUE2 has no owner |
| 830 RESTRICTED_ISSUE2.cc_ids.append(CC_ID) |
| 831 RESTRICTED_ISSUE2.labels.append('Restrict-View-Commit') |
| 832 |
| 833 RESTRICTED_ISSUE3 = tracker_pb2.Issue() |
| 834 RESTRICTED_ISSUE3.reporter_id = REPORTER_ID |
| 835 RESTRICTED_ISSUE3.owner_id = OWNER_ID |
| 836 # Restrict to a permission that no one has. |
| 837 RESTRICTED_ISSUE3.labels.append('Restrict-EditIssue-Foo') |
| 838 |
| 839 PROJECT = project_pb2.Project() |
| 840 |
| 841 def testCanViewIssue_Deleted(self): |
| 842 self.assertFalse(permissions.CanViewIssue( |
| 843 {REPORTER_ID}, permissions.OWNER_ACTIVE_PERMISSIONSET, |
| 844 self.PROJECT, self.DELETED_ISSUE)) |
| 845 self.assertTrue(permissions.CanViewIssue( |
| 846 {REPORTER_ID}, permissions.OWNER_ACTIVE_PERMISSIONSET, |
| 847 self.PROJECT, self.DELETED_ISSUE, allow_viewing_deleted=True)) |
| 848 self.assertTrue(permissions.CanViewIssue( |
| 849 {REPORTER_ID}, permissions.OWNER_ACTIVE_PERMISSIONSET, |
| 850 self.PROJECT, self.REGULAR_ISSUE)) |
| 851 |
| 852 def testCanViewIssue_Regular(self): |
| 853 self.assertTrue(permissions.CanViewIssue( |
| 854 {REPORTER_ID}, permissions.OWNER_ACTIVE_PERMISSIONSET, |
| 855 self.PROJECT, self.REGULAR_ISSUE)) |
| 856 self.assertTrue(permissions.CanViewIssue( |
| 857 {REPORTER_ID}, permissions.COMMITTER_ACTIVE_PERMISSIONSET, |
| 858 self.PROJECT, self.REGULAR_ISSUE)) |
| 859 self.assertTrue(permissions.CanViewIssue( |
| 860 {REPORTER_ID}, |
| 861 permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET, |
| 862 self.PROJECT, self.REGULAR_ISSUE)) |
| 863 self.assertTrue(permissions.CanViewIssue( |
| 864 {REPORTER_ID}, permissions.USER_PERMISSIONSET, |
| 865 self.PROJECT, self.REGULAR_ISSUE)) |
| 866 self.assertTrue(permissions.CanViewIssue( |
| 867 {REPORTER_ID}, permissions.READ_ONLY_PERMISSIONSET, |
| 868 self.PROJECT, self.REGULAR_ISSUE)) |
| 869 self.assertTrue(permissions.CanViewIssue( |
| 870 set(), permissions.READ_ONLY_PERMISSIONSET, |
| 871 self.PROJECT, self.REGULAR_ISSUE)) |
| 872 |
| 873 def testCanViewIssue_Restricted(self): |
| 874 # Project owner can always view issue. |
| 875 self.assertTrue(permissions.CanViewIssue( |
| 876 {OTHER_ID}, permissions.OWNER_ACTIVE_PERMISSIONSET, |
| 877 self.PROJECT, self.RESTRICTED_ISSUE)) |
| 878 # Member can view because they have Commit perm. |
| 879 self.assertTrue(permissions.CanViewIssue( |
| 880 {OTHER_ID}, permissions.COMMITTER_ACTIVE_PERMISSIONSET, |
| 881 self.PROJECT, self.RESTRICTED_ISSUE)) |
| 882 # Contributors normally do not have Commit perm. |
| 883 self.assertFalse(permissions.CanViewIssue( |
| 884 {OTHER_ID}, permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET, |
| 885 self.PROJECT, self.RESTRICTED_ISSUE)) |
| 886 # Non-members do not have Commit perm. |
| 887 self.assertFalse(permissions.CanViewIssue( |
| 888 {OTHER_ID}, permissions.USER_PERMISSIONSET, |
| 889 self.PROJECT, self.RESTRICTED_ISSUE)) |
| 890 # Anon user's do not have Commit perm. |
| 891 self.assertFalse(permissions.CanViewIssue( |
| 892 set(), permissions.READ_ONLY_PERMISSIONSET, |
| 893 self.PROJECT, self.RESTRICTED_ISSUE)) |
| 894 |
| 895 def testCanViewIssue_RestrictedParticipants(self): |
| 896 # Reporter can always view issue |
| 897 self.assertTrue(permissions.CanViewIssue( |
| 898 {REPORTER_ID}, permissions.READ_ONLY_PERMISSIONSET, |
| 899 self.PROJECT, self.RESTRICTED_ISSUE)) |
| 900 # Issue owner can always view issue |
| 901 self.assertTrue(permissions.CanViewIssue( |
| 902 {OWNER_ID}, permissions.READ_ONLY_PERMISSIONSET, |
| 903 self.PROJECT, self.RESTRICTED_ISSUE)) |
| 904 # CC'd user can always view issue |
| 905 self.assertTrue(permissions.CanViewIssue( |
| 906 {CC_ID}, permissions.READ_ONLY_PERMISSIONSET, |
| 907 self.PROJECT, self.RESTRICTED_ISSUE)) |
| 908 # Non-participants cannot view issue if they don't have the needed perm. |
| 909 self.assertFalse(permissions.CanViewIssue( |
| 910 {OTHER_ID}, permissions.READ_ONLY_PERMISSIONSET, |
| 911 self.PROJECT, self.RESTRICTED_ISSUE)) |
| 912 # Anon user's do not have Commit perm. |
| 913 self.assertFalse(permissions.CanViewIssue( |
| 914 set(), permissions.READ_ONLY_PERMISSIONSET, |
| 915 self.PROJECT, self.RESTRICTED_ISSUE)) |
| 916 # Anon user's cannot match owner 0. |
| 917 self.assertFalse(permissions.CanViewIssue( |
| 918 set(), permissions.READ_ONLY_PERMISSIONSET, |
| 919 self.PROJECT, self.RESTRICTED_ISSUE2)) |
| 920 |
| 921 def testCannotViewIssueIfCannotViewProject(self): |
| 922 """Cross-project search should not be a backdoor to viewing issues.""" |
| 923 # Reporter cannot view issue if they not long have access to the project. |
| 924 self.assertFalse(permissions.CanViewIssue( |
| 925 {REPORTER_ID}, permissions.EMPTY_PERMISSIONSET, |
| 926 self.PROJECT, self.REGULAR_ISSUE)) |
| 927 # Issue owner cannot always view issue |
| 928 self.assertFalse(permissions.CanViewIssue( |
| 929 {OWNER_ID}, permissions.EMPTY_PERMISSIONSET, |
| 930 self.PROJECT, self.REGULAR_ISSUE)) |
| 931 # CC'd user cannot always view issue |
| 932 self.assertFalse(permissions.CanViewIssue( |
| 933 {CC_ID}, permissions.EMPTY_PERMISSIONSET, |
| 934 self.PROJECT, self.REGULAR_ISSUE)) |
| 935 # Non-participants cannot view issue if they don't have the needed perm. |
| 936 self.assertFalse(permissions.CanViewIssue( |
| 937 {OTHER_ID}, permissions.EMPTY_PERMISSIONSET, |
| 938 self.PROJECT, self.REGULAR_ISSUE)) |
| 939 # Anon user's do not have Commit perm. |
| 940 self.assertFalse(permissions.CanViewIssue( |
| 941 set(), permissions.EMPTY_PERMISSIONSET, self.PROJECT, |
| 942 self.REGULAR_ISSUE)) |
| 943 # Anon user's cannot match owner 0. |
| 944 self.assertFalse(permissions.CanViewIssue( |
| 945 set(), permissions.EMPTY_PERMISSIONSET, self.PROJECT, |
| 946 self.REGULAR_ISSUE)) |
| 947 |
| 948 def testCanEditIssue(self): |
| 949 # Non-members and contributors cannot edit issues, |
| 950 # even if they reported them. |
| 951 self.assertFalse(permissions.CanEditIssue( |
| 952 {REPORTER_ID}, permissions.READ_ONLY_PERMISSIONSET, |
| 953 self.PROJECT, self.REGULAR_ISSUE)) |
| 954 self.assertFalse(permissions.CanEditIssue( |
| 955 {REPORTER_ID}, permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET, |
| 956 self.PROJECT, self.REGULAR_ISSUE)) |
| 957 |
| 958 # Project committers and project owners can edit issues, regardless |
| 959 # of their role in the issue. |
| 960 self.assertTrue(permissions.CanEditIssue( |
| 961 {REPORTER_ID}, permissions.COMMITTER_ACTIVE_PERMISSIONSET, |
| 962 self.PROJECT, self.REGULAR_ISSUE)) |
| 963 self.assertTrue(permissions.CanEditIssue( |
| 964 {REPORTER_ID}, permissions.OWNER_ACTIVE_PERMISSIONSET, |
| 965 self.PROJECT, self.REGULAR_ISSUE)) |
| 966 self.assertTrue(permissions.CanEditIssue( |
| 967 {OWNER_ID}, permissions.COMMITTER_ACTIVE_PERMISSIONSET, |
| 968 self.PROJECT, self.REGULAR_ISSUE)) |
| 969 self.assertTrue(permissions.CanEditIssue( |
| 970 {OWNER_ID}, permissions.OWNER_ACTIVE_PERMISSIONSET, |
| 971 self.PROJECT, self.REGULAR_ISSUE)) |
| 972 self.assertTrue(permissions.CanEditIssue( |
| 973 {OTHER_ID}, permissions.COMMITTER_ACTIVE_PERMISSIONSET, |
| 974 self.PROJECT, self.REGULAR_ISSUE)) |
| 975 self.assertTrue(permissions.CanEditIssue( |
| 976 {OTHER_ID}, permissions.OWNER_ACTIVE_PERMISSIONSET, |
| 977 self.PROJECT, self.REGULAR_ISSUE)) |
| 978 |
| 979 def testCanEditIssue_Restricted(self): |
| 980 # Project committers cannot edit issues with a restriction to a custom |
| 981 # permission that they don't have. |
| 982 self.assertFalse(permissions.CanEditIssue( |
| 983 {OTHER_ID}, permissions.COMMITTER_ACTIVE_PERMISSIONSET, |
| 984 self.PROJECT, self.RESTRICTED_ISSUE3)) |
| 985 |
| 986 # *Issue* owners can always edit the issues that they own, even if |
| 987 # those issues are restricted to perms that they don't have. |
| 988 self.assertTrue(permissions.CanEditIssue( |
| 989 {OWNER_ID}, permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET, |
| 990 self.PROJECT, self.RESTRICTED_ISSUE3)) |
| 991 |
| 992 # Project owners can always edit, they cannot lock themselves out. |
| 993 self.assertTrue(permissions.CanEditIssue( |
| 994 {OTHER_ID}, permissions.OWNER_ACTIVE_PERMISSIONSET, |
| 995 self.PROJECT, self.RESTRICTED_ISSUE3)) |
| 996 |
| 997 # A committer with edit permission but not view permission |
| 998 # should not be able to edit the issue. |
| 999 self.assertFalse(permissions.CanEditIssue( |
| 1000 {OTHER_ID}, permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET, |
| 1001 self.PROJECT, self.RESTRICTED_ISSUE2)) |
| 1002 |
| 1003 def testCanCommentIssue_HasPerm(self): |
| 1004 self.assertTrue(permissions.CanCommentIssue( |
| 1005 {111L}, permissions.PermissionSet([permissions.ADD_ISSUE_COMMENT]), |
| 1006 None, None)) |
| 1007 self.assertFalse(permissions.CanCommentIssue( |
| 1008 {111L}, permissions.PermissionSet([]), |
| 1009 None, None)) |
| 1010 |
| 1011 def testCanCommentIssue_HasExtraPerm(self): |
| 1012 project = project_pb2.Project() |
| 1013 project.committer_ids.append(111L) |
| 1014 extra_perm = project_pb2.Project.ExtraPerms( |
| 1015 member_id=111L, perms=[permissions.ADD_ISSUE_COMMENT]) |
| 1016 project.extra_perms.append(extra_perm) |
| 1017 self.assertTrue(permissions.CanCommentIssue( |
| 1018 {111L}, permissions.PermissionSet([]), |
| 1019 project, None)) |
| 1020 self.assertFalse(permissions.CanCommentIssue( |
| 1021 {222L}, permissions.PermissionSet([]), |
| 1022 project, None)) |
| 1023 |
| 1024 def testCanCommentIssue_Restricted(self): |
| 1025 issue = tracker_pb2.Issue(labels=['Restrict-AddIssueComment-CoreTeam']) |
| 1026 # User is granted exactly the perm they need specifically in this issue. |
| 1027 self.assertTrue(permissions.CanCommentIssue( |
| 1028 {111L}, permissions.PermissionSet([]), |
| 1029 None, issue, granted_perms=['addissuecomment'])) |
| 1030 # User is granted CoreTeam, which satifies the restriction, and allows |
| 1031 # them to use the AddIssueComment permission that they have and would |
| 1032 # normally be able to use in an unrestricted issue. |
| 1033 self.assertTrue(permissions.CanCommentIssue( |
| 1034 {111L}, permissions.PermissionSet([permissions.ADD_ISSUE_COMMENT]), |
| 1035 None, issue, granted_perms=['coreteam'])) |
| 1036 # User was granted CoreTeam, but never had AddIssueComment. |
| 1037 self.assertFalse(permissions.CanCommentIssue( |
| 1038 {111L}, permissions.PermissionSet([]), |
| 1039 None, issue, granted_perms=['coreteam'])) |
| 1040 # User has AddIssueComment, but cannot satisfy restriction. |
| 1041 self.assertFalse(permissions.CanCommentIssue( |
| 1042 {111L}, permissions.PermissionSet([permissions.ADD_ISSUE_COMMENT]), |
| 1043 None, issue)) |
| 1044 |
| 1045 def testCanCommentIssue_Granted(self): |
| 1046 self.assertTrue(permissions.CanCommentIssue( |
| 1047 {111L}, permissions.PermissionSet([]), |
| 1048 None, None, granted_perms=['addissuecomment'])) |
| 1049 self.assertFalse(permissions.CanCommentIssue( |
| 1050 {111L}, permissions.PermissionSet([]), |
| 1051 None, None)) |
| 1052 |
| 1053 def testCanViewComponentDef_ComponentAdmin(self): |
| 1054 cd = tracker_pb2.ComponentDef(admin_ids=[111L]) |
| 1055 perms = permissions.PermissionSet([]) |
| 1056 self.assertTrue(permissions.CanViewComponentDef( |
| 1057 {111L}, perms, None, cd)) |
| 1058 self.assertFalse(permissions.CanViewComponentDef( |
| 1059 {999L}, perms, None, cd)) |
| 1060 |
| 1061 def testCanViewComponentDef_NormalUser(self): |
| 1062 cd = tracker_pb2.ComponentDef() |
| 1063 self.assertTrue(permissions.CanViewComponentDef( |
| 1064 {111L}, permissions.PermissionSet([permissions.VIEW]), |
| 1065 None, cd)) |
| 1066 self.assertFalse(permissions.CanViewComponentDef( |
| 1067 {111L}, permissions.PermissionSet([]), |
| 1068 None, cd)) |
| 1069 |
| 1070 def testCanEditComponentDef_ComponentAdmin(self): |
| 1071 cd = tracker_pb2.ComponentDef(admin_ids=[111L], path='Whole') |
| 1072 sub_cd = tracker_pb2.ComponentDef(admin_ids=[222L], path='Whole>Part') |
| 1073 config = tracker_bizobj.MakeDefaultProjectIssueConfig(789) |
| 1074 config.component_defs.append(cd) |
| 1075 config.component_defs.append(sub_cd) |
| 1076 perms = permissions.PermissionSet([]) |
| 1077 self.assertTrue(permissions.CanEditComponentDef( |
| 1078 {111L}, perms, None, cd, config)) |
| 1079 self.assertFalse(permissions.CanEditComponentDef( |
| 1080 {222L}, perms, None, cd, config)) |
| 1081 self.assertFalse(permissions.CanEditComponentDef( |
| 1082 {999L}, perms, None, cd, config)) |
| 1083 self.assertTrue(permissions.CanEditComponentDef( |
| 1084 {111L}, perms, None, sub_cd, config)) |
| 1085 self.assertTrue(permissions.CanEditComponentDef( |
| 1086 {222L}, perms, None, sub_cd, config)) |
| 1087 self.assertFalse(permissions.CanEditComponentDef( |
| 1088 {999L}, perms, None, sub_cd, config)) |
| 1089 |
| 1090 def testCanEditComponentDef_ProjectOwners(self): |
| 1091 cd = tracker_pb2.ComponentDef(path='Whole') |
| 1092 config = tracker_bizobj.MakeDefaultProjectIssueConfig(789) |
| 1093 config.component_defs.append(cd) |
| 1094 self.assertTrue(permissions.CanEditComponentDef( |
| 1095 {111L}, permissions.PermissionSet([permissions.EDIT_PROJECT]), |
| 1096 None, cd, config)) |
| 1097 self.assertFalse(permissions.CanEditComponentDef( |
| 1098 {111L}, permissions.PermissionSet([]), |
| 1099 None, cd, config)) |
| 1100 |
| 1101 def testCanViewFieldDef_FieldAdmin(self): |
| 1102 fd = tracker_pb2.FieldDef(admin_ids=[111L]) |
| 1103 perms = permissions.PermissionSet([]) |
| 1104 self.assertTrue(permissions.CanViewFieldDef( |
| 1105 {111L}, perms, None, fd)) |
| 1106 self.assertFalse(permissions.CanViewFieldDef( |
| 1107 {999L}, perms, None, fd)) |
| 1108 |
| 1109 def testCanViewFieldDef_NormalUser(self): |
| 1110 fd = tracker_pb2.FieldDef() |
| 1111 self.assertTrue(permissions.CanViewFieldDef( |
| 1112 {111L}, permissions.PermissionSet([permissions.VIEW]), |
| 1113 None, fd)) |
| 1114 self.assertFalse(permissions.CanViewFieldDef( |
| 1115 {111L}, permissions.PermissionSet([]), |
| 1116 None, fd)) |
| 1117 |
| 1118 def testCanEditFieldDef_FieldAdmin(self): |
| 1119 fd = tracker_pb2.FieldDef(admin_ids=[111L]) |
| 1120 perms = permissions.PermissionSet([]) |
| 1121 self.assertTrue(permissions.CanEditFieldDef( |
| 1122 {111L}, perms, None, fd)) |
| 1123 self.assertFalse(permissions.CanEditFieldDef( |
| 1124 {999L}, perms, None, fd)) |
| 1125 |
| 1126 def testCanEditFieldDef_ProjectOwners(self): |
| 1127 fd = tracker_pb2.FieldDef() |
| 1128 self.assertTrue(permissions.CanEditFieldDef( |
| 1129 {111L}, permissions.PermissionSet([permissions.EDIT_PROJECT]), |
| 1130 None, fd)) |
| 1131 self.assertFalse(permissions.CanEditFieldDef( |
| 1132 {111L}, permissions.PermissionSet([]), |
| 1133 None, fd)) |
| 1134 |
| 1135 def testCanViewTemplate_TemplateAdmin(self): |
| 1136 td = tracker_pb2.TemplateDef(admin_ids=[111L]) |
| 1137 perms = permissions.PermissionSet([]) |
| 1138 self.assertTrue(permissions.CanViewTemplate( |
| 1139 {111L}, perms, None, td)) |
| 1140 self.assertFalse(permissions.CanViewTemplate( |
| 1141 {999L}, perms, None, td)) |
| 1142 |
| 1143 def testCanViewTemplate_MembersOnly(self): |
| 1144 td = tracker_pb2.TemplateDef(members_only=True) |
| 1145 project = project_pb2.Project(committer_ids=[111L]) |
| 1146 self.assertTrue(permissions.CanViewTemplate( |
| 1147 {111L}, permissions.PermissionSet([]), |
| 1148 project, td)) |
| 1149 self.assertFalse(permissions.CanViewTemplate( |
| 1150 {999L}, permissions.PermissionSet([]), |
| 1151 project, td)) |
| 1152 |
| 1153 def testCanViewTemplate_AnyoneWhoCanViewProject(self): |
| 1154 td = tracker_pb2.TemplateDef() |
| 1155 self.assertTrue(permissions.CanViewTemplate( |
| 1156 {111L}, permissions.PermissionSet([permissions.VIEW]), |
| 1157 None, td)) |
| 1158 self.assertFalse(permissions.CanViewTemplate( |
| 1159 {111L}, permissions.PermissionSet([]), |
| 1160 None, td)) |
| 1161 |
| 1162 def testCanEditTemplate_TemplateAdmin(self): |
| 1163 td = tracker_pb2.TemplateDef(admin_ids=[111L]) |
| 1164 perms = permissions.PermissionSet([]) |
| 1165 self.assertTrue(permissions.CanEditTemplate( |
| 1166 {111L}, perms, None, td)) |
| 1167 self.assertFalse(permissions.CanEditTemplate( |
| 1168 {999L}, perms, None, td)) |
| 1169 |
| 1170 def testCanEditTemplate_ProjectOwners(self): |
| 1171 td = tracker_pb2.TemplateDef() |
| 1172 self.assertTrue(permissions.CanEditTemplate( |
| 1173 {111L}, permissions.PermissionSet([permissions.EDIT_PROJECT]), |
| 1174 None, td)) |
| 1175 self.assertFalse(permissions.CanEditTemplate( |
| 1176 {111L}, permissions.PermissionSet([]), |
| 1177 None, td)) |
| 1178 |
| 1179 |
| 1180 if __name__ == '__main__': |
| 1181 unittest.main() |
OLD | NEW |