Copybara | 854996b | 2021-09-07 19:36:02 +0000 | [diff] [blame] | 1 | # Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 | # Use of this source code is governed 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 | from __future__ import print_function |
| 8 | from __future__ import division |
| 9 | from __future__ import absolute_import |
| 10 | |
| 11 | import time |
| 12 | import unittest |
| 13 | |
| 14 | import mox |
| 15 | |
| 16 | import settings |
| 17 | from framework import authdata |
| 18 | from framework import framework_constants |
| 19 | from framework import framework_views |
| 20 | from framework import permissions |
| 21 | from proto import features_pb2 |
| 22 | from proto import project_pb2 |
| 23 | from proto import site_pb2 |
| 24 | from proto import tracker_pb2 |
| 25 | from proto import user_pb2 |
| 26 | from proto import usergroup_pb2 |
| 27 | from testing import fake |
| 28 | from testing import testing_helpers |
| 29 | from tracker import tracker_bizobj |
| 30 | |
| 31 | |
| 32 | class PermissionSetTest(unittest.TestCase): |
| 33 | |
| 34 | def setUp(self): |
| 35 | self.perms = permissions.PermissionSet(['A', 'b', 'Cc']) |
| 36 | self.proj = project_pb2.Project() |
| 37 | self.proj.contributor_ids.append(111) |
| 38 | self.proj.contributor_ids.append(222) |
| 39 | self.proj.extra_perms.append(project_pb2.Project.ExtraPerms( |
| 40 | member_id=111, perms=['Cc', 'D', 'e', 'Ff'])) |
| 41 | self.proj.extra_perms.append(project_pb2.Project.ExtraPerms( |
| 42 | member_id=222, perms=['G', 'H'])) |
| 43 | # user 3 used to be a member and had extra perms, but no longer in project. |
| 44 | self.proj.extra_perms.append(project_pb2.Project.ExtraPerms( |
| 45 | member_id=333, perms=['G', 'H'])) |
| 46 | |
| 47 | def testGetAttr(self): |
| 48 | self.assertTrue(self.perms.a) |
| 49 | self.assertTrue(self.perms.A) |
| 50 | self.assertTrue(self.perms.b) |
| 51 | self.assertTrue(self.perms.Cc) |
| 52 | self.assertTrue(self.perms.CC) |
| 53 | |
| 54 | self.assertFalse(self.perms.z) |
| 55 | self.assertFalse(self.perms.Z) |
| 56 | |
| 57 | def testCanUsePerm_Anonymous(self): |
| 58 | effective_ids = set() |
| 59 | self.assertTrue(self.perms.CanUsePerm('A', effective_ids, self.proj, [])) |
| 60 | self.assertFalse(self.perms.CanUsePerm('D', effective_ids, self.proj, [])) |
| 61 | self.assertFalse(self.perms.CanUsePerm('Z', effective_ids, self.proj, [])) |
| 62 | |
| 63 | def testCanUsePerm_SignedInNoGroups(self): |
| 64 | effective_ids = {111} |
| 65 | self.assertTrue(self.perms.CanUsePerm('A', effective_ids, self.proj, [])) |
| 66 | self.assertTrue(self.perms.CanUsePerm('D', effective_ids, self.proj, [])) |
| 67 | self.assertTrue(self.perms.CanUsePerm( |
| 68 | 'D', effective_ids, self.proj, ['Restrict-D-A'])) |
| 69 | self.assertFalse(self.perms.CanUsePerm('G', effective_ids, self.proj, [])) |
| 70 | self.assertFalse(self.perms.CanUsePerm('Z', effective_ids, self.proj, [])) |
| 71 | |
| 72 | effective_ids = {222} |
| 73 | self.assertTrue(self.perms.CanUsePerm('A', effective_ids, self.proj, [])) |
| 74 | self.assertFalse(self.perms.CanUsePerm('D', effective_ids, self.proj, [])) |
| 75 | self.assertTrue(self.perms.CanUsePerm('G', effective_ids, self.proj, [])) |
| 76 | self.assertFalse(self.perms.CanUsePerm('Z', effective_ids, self.proj, [])) |
| 77 | self.assertFalse(self.perms.CanUsePerm( |
| 78 | 'Z', effective_ids, self.proj, ['Restrict-Z-A'])) |
| 79 | |
| 80 | def testCanUsePerm_SignedInWithGroups(self): |
| 81 | effective_ids = {111, 222, 333} |
| 82 | self.assertTrue(self.perms.CanUsePerm('A', effective_ids, self.proj, [])) |
| 83 | self.assertTrue(self.perms.CanUsePerm('D', effective_ids, self.proj, [])) |
| 84 | self.assertTrue(self.perms.CanUsePerm('G', effective_ids, self.proj, [])) |
| 85 | self.assertTrue(self.perms.CanUsePerm( |
| 86 | 'G', effective_ids, self.proj, ['Restrict-G-D'])) |
| 87 | self.assertFalse(self.perms.CanUsePerm('Z', effective_ids, self.proj, [])) |
| 88 | self.assertFalse(self.perms.CanUsePerm( |
| 89 | 'G', effective_ids, self.proj, ['Restrict-G-Z'])) |
| 90 | |
| 91 | def testCanUsePerm_FormerMember(self): |
| 92 | effective_ids = {333} |
| 93 | self.assertTrue(self.perms.CanUsePerm('A', effective_ids, self.proj, [])) |
| 94 | self.assertFalse(self.perms.CanUsePerm('D', effective_ids, self.proj, [])) |
| 95 | self.assertFalse(self.perms.CanUsePerm('G', effective_ids, self.proj, [])) |
| 96 | self.assertFalse(self.perms.CanUsePerm('Z', effective_ids, self.proj, [])) |
| 97 | |
| 98 | def testHasPerm_InPermSet(self): |
| 99 | self.assertTrue(self.perms.HasPerm('a', 0, None)) |
| 100 | self.assertTrue(self.perms.HasPerm('a', 0, self.proj)) |
| 101 | self.assertTrue(self.perms.HasPerm('A', 0, None)) |
| 102 | self.assertTrue(self.perms.HasPerm('A', 0, self.proj)) |
| 103 | self.assertFalse(self.perms.HasPerm('Z', 0, None)) |
| 104 | self.assertFalse(self.perms.HasPerm('Z', 0, self.proj)) |
| 105 | |
| 106 | def testHasPerm_InExtraPerms(self): |
| 107 | self.assertTrue(self.perms.HasPerm('d', 111, self.proj)) |
| 108 | self.assertTrue(self.perms.HasPerm('D', 111, self.proj)) |
| 109 | self.assertTrue(self.perms.HasPerm('Cc', 111, self.proj)) |
| 110 | self.assertTrue(self.perms.HasPerm('CC', 111, self.proj)) |
| 111 | self.assertFalse(self.perms.HasPerm('Z', 111, self.proj)) |
| 112 | |
| 113 | self.assertFalse(self.perms.HasPerm('d', 222, self.proj)) |
| 114 | self.assertFalse(self.perms.HasPerm('D', 222, self.proj)) |
| 115 | |
| 116 | # Only current members can have extra permissions |
| 117 | self.proj.contributor_ids = [] |
| 118 | self.assertFalse(self.perms.HasPerm('d', 111, self.proj)) |
| 119 | |
| 120 | # TODO(jrobbins): also test consider_restrictions=False and |
| 121 | # restriction labels directly in this class. |
| 122 | |
| 123 | def testHasPerm_OverrideExtraPerms(self): |
| 124 | # D is an extra perm for 111... |
| 125 | self.assertTrue(self.perms.HasPerm('d', 111, self.proj)) |
| 126 | self.assertTrue(self.perms.HasPerm('D', 111, self.proj)) |
| 127 | # ...unless we tell HasPerm it isn't. |
| 128 | self.assertFalse(self.perms.HasPerm('d', 111, self.proj, [])) |
| 129 | self.assertFalse(self.perms.HasPerm('D', 111, self.proj, [])) |
| 130 | # Perms in self.perms are still considered |
| 131 | self.assertTrue(self.perms.HasPerm('Cc', 111, self.proj, [])) |
| 132 | self.assertTrue(self.perms.HasPerm('CC', 111, self.proj, [])) |
| 133 | # Z is not an extra perm... |
| 134 | self.assertFalse(self.perms.HasPerm('Z', 111, self.proj)) |
| 135 | # ...unless we tell HasPerm it is. |
| 136 | self.assertTrue(self.perms.HasPerm('Z', 111, self.proj, ['z'])) |
| 137 | |
| 138 | def testHasPerm_GrantedPerms(self): |
| 139 | self.assertTrue(self.perms.CanUsePerm( |
| 140 | 'A', {111}, self.proj, [], granted_perms=['z'])) |
| 141 | self.assertTrue(self.perms.CanUsePerm( |
| 142 | 'a', {111}, self.proj, [], granted_perms=['z'])) |
| 143 | self.assertTrue(self.perms.CanUsePerm( |
| 144 | 'a', {111}, self.proj, [], granted_perms=['a'])) |
| 145 | self.assertTrue(self.perms.CanUsePerm( |
| 146 | 'Z', {111}, self.proj, [], granted_perms=['y', 'z'])) |
| 147 | self.assertTrue(self.perms.CanUsePerm( |
| 148 | 'z', {111}, self.proj, [], granted_perms=['y', 'z'])) |
| 149 | self.assertFalse(self.perms.CanUsePerm( |
| 150 | 'z', {111}, self.proj, [], granted_perms=['y'])) |
| 151 | |
| 152 | def testDebugString(self): |
| 153 | self.assertEqual('PermissionSet()', |
| 154 | permissions.PermissionSet([]).DebugString()) |
| 155 | self.assertEqual('PermissionSet(a)', |
| 156 | permissions.PermissionSet(['A']).DebugString()) |
| 157 | self.assertEqual('PermissionSet(a, b, cc)', self.perms.DebugString()) |
| 158 | |
| 159 | def testRepr(self): |
| 160 | self.assertEqual('PermissionSet(frozenset([]))', |
| 161 | permissions.PermissionSet([]).__repr__()) |
| 162 | self.assertEqual('PermissionSet(frozenset([\'a\']))', |
| 163 | permissions.PermissionSet(['A']).__repr__()) |
| 164 | |
| 165 | |
| 166 | class PermissionsTest(unittest.TestCase): |
| 167 | |
| 168 | NOW = 1277762224 # Any timestamp will do, we only compare it to itself +/- 1 |
| 169 | COMMITTER_USER_ID = 111 |
| 170 | OWNER_USER_ID = 222 |
| 171 | CONTRIB_USER_ID = 333 |
| 172 | SITE_ADMIN_USER_ID = 444 |
| 173 | |
| 174 | def MakeProject(self, project_name, state, add_members=True, access=None): |
| 175 | args = dict(project_name=project_name, state=state) |
| 176 | if add_members: |
| 177 | args.update(owner_ids=[self.OWNER_USER_ID], |
| 178 | committer_ids=[self.COMMITTER_USER_ID], |
| 179 | contributor_ids=[self.CONTRIB_USER_ID]) |
| 180 | |
| 181 | if access: |
| 182 | args.update(access=access) |
| 183 | |
| 184 | return fake.Project(**args) |
| 185 | |
| 186 | def setUp(self): |
| 187 | self.live_project = self.MakeProject('live', project_pb2.ProjectState.LIVE) |
| 188 | self.archived_project = self.MakeProject( |
| 189 | 'archived', project_pb2.ProjectState.ARCHIVED) |
| 190 | self.other_live_project = self.MakeProject( |
| 191 | 'other_live', project_pb2.ProjectState.LIVE, add_members=False) |
| 192 | self.members_only_project = self.MakeProject( |
| 193 | 's3kr3t', project_pb2.ProjectState.LIVE, |
| 194 | access=project_pb2.ProjectAccess.MEMBERS_ONLY) |
| 195 | |
| 196 | self.nonmember = user_pb2.User() |
| 197 | self.member = user_pb2.User() |
| 198 | self.owner = user_pb2.User() |
| 199 | self.contrib = user_pb2.User() |
| 200 | self.site_admin = user_pb2.User() |
| 201 | self.site_admin.is_site_admin = True |
| 202 | self.borg_user = user_pb2.User(email=settings.borg_service_account) |
| 203 | |
| 204 | self.normal_artifact = tracker_pb2.Issue() |
| 205 | self.normal_artifact.labels.extend(['hot', 'Key-Value']) |
| 206 | self.normal_artifact.reporter_id = 111 |
| 207 | |
| 208 | # Two PermissionSets w/ permissions outside of any project. |
| 209 | self.normal_user_perms = permissions.GetPermissions( |
| 210 | None, {111}, None) |
| 211 | self.admin_perms = permissions.PermissionSet( |
| 212 | [permissions.ADMINISTER_SITE, |
| 213 | permissions.CREATE_PROJECT]) |
| 214 | |
| 215 | self.mox = mox.Mox() |
| 216 | |
| 217 | def tearDown(self): |
| 218 | self.mox.UnsetStubs() |
| 219 | |
| 220 | def testGetPermissions_Admin(self): |
| 221 | self.assertEqual( |
| 222 | permissions.ADMIN_PERMISSIONSET, |
| 223 | permissions.GetPermissions(self.site_admin, None, None)) |
| 224 | |
| 225 | def testGetPermissions_BorgServiceAccount(self): |
| 226 | self.assertEqual( |
| 227 | permissions.GROUP_IMPORT_BORG_PERMISSIONSET, |
| 228 | permissions.GetPermissions(self.borg_user, None, None)) |
| 229 | |
| 230 | def CheckPermissions(self, perms, expected_list): |
| 231 | expect_view, expect_commit, expect_edit_project = expected_list |
| 232 | self.assertEqual( |
| 233 | expect_view, perms.HasPerm(permissions.VIEW, None, None)) |
| 234 | self.assertEqual( |
| 235 | expect_commit, perms.HasPerm(permissions.COMMIT, None, None)) |
| 236 | self.assertEqual( |
| 237 | expect_edit_project, |
| 238 | perms.HasPerm(permissions.EDIT_PROJECT, None, None)) |
| 239 | |
| 240 | def testAnonPermissions(self): |
| 241 | perms = permissions.GetPermissions(None, set(), self.live_project) |
| 242 | self.CheckPermissions(perms, [True, False, False]) |
| 243 | |
| 244 | perms = permissions.GetPermissions(None, set(), self.members_only_project) |
| 245 | self.CheckPermissions(perms, [False, False, False]) |
| 246 | |
| 247 | def testNonmemberPermissions(self): |
| 248 | perms = permissions.GetPermissions( |
| 249 | self.nonmember, {123}, self.live_project) |
| 250 | self.CheckPermissions(perms, [True, False, False]) |
| 251 | |
| 252 | perms = permissions.GetPermissions( |
| 253 | self.nonmember, {123}, self.members_only_project) |
| 254 | self.CheckPermissions(perms, [False, False, False]) |
| 255 | |
| 256 | def testMemberPermissions(self): |
| 257 | perms = permissions.GetPermissions( |
| 258 | self.member, {self.COMMITTER_USER_ID}, self.live_project) |
| 259 | self.CheckPermissions(perms, [True, True, False]) |
| 260 | |
| 261 | perms = permissions.GetPermissions( |
| 262 | self.member, {self.COMMITTER_USER_ID}, self.other_live_project) |
| 263 | self.CheckPermissions(perms, [True, False, False]) |
| 264 | |
| 265 | perms = permissions.GetPermissions( |
| 266 | self.member, {self.COMMITTER_USER_ID}, self.members_only_project) |
| 267 | self.CheckPermissions(perms, [True, True, False]) |
| 268 | |
| 269 | def testOwnerPermissions(self): |
| 270 | perms = permissions.GetPermissions( |
| 271 | self.owner, {self.OWNER_USER_ID}, self.live_project) |
| 272 | self.CheckPermissions(perms, [True, True, True]) |
| 273 | |
| 274 | perms = permissions.GetPermissions( |
| 275 | self.owner, {self.OWNER_USER_ID}, self.other_live_project) |
| 276 | self.CheckPermissions(perms, [True, False, False]) |
| 277 | |
| 278 | perms = permissions.GetPermissions( |
| 279 | self.owner, {self.OWNER_USER_ID}, self.members_only_project) |
| 280 | self.CheckPermissions(perms, [True, True, True]) |
| 281 | |
| 282 | def testContributorPermissions(self): |
| 283 | perms = permissions.GetPermissions( |
| 284 | self.contrib, {self.CONTRIB_USER_ID}, self.live_project) |
| 285 | self.CheckPermissions(perms, [True, False, False]) |
| 286 | |
| 287 | perms = permissions.GetPermissions( |
| 288 | self.contrib, {self.CONTRIB_USER_ID}, self.other_live_project) |
| 289 | self.CheckPermissions(perms, [True, False, False]) |
| 290 | |
| 291 | perms = permissions.GetPermissions( |
| 292 | self.contrib, {self.CONTRIB_USER_ID}, self.members_only_project) |
| 293 | self.CheckPermissions(perms, [True, False, False]) |
| 294 | |
| 295 | def testLookupPermset_ExactMatch(self): |
| 296 | self.assertEqual( |
| 297 | permissions.USER_PERMISSIONSET, |
| 298 | permissions._LookupPermset( |
| 299 | permissions.USER_ROLE, project_pb2.ProjectState.LIVE, |
| 300 | project_pb2.ProjectAccess.ANYONE)) |
| 301 | |
| 302 | def testLookupPermset_WildcardAccess(self): |
| 303 | self.assertEqual( |
| 304 | permissions.OWNER_ACTIVE_PERMISSIONSET, |
| 305 | permissions._LookupPermset( |
| 306 | permissions.OWNER_ROLE, project_pb2.ProjectState.LIVE, |
| 307 | project_pb2.ProjectAccess.MEMBERS_ONLY)) |
| 308 | |
| 309 | def testGetPermissionKey_AnonUser(self): |
| 310 | self.assertEqual( |
| 311 | (permissions.ANON_ROLE, permissions.UNDEFINED_STATUS, |
| 312 | permissions.UNDEFINED_ACCESS), |
| 313 | permissions._GetPermissionKey(None, None)) |
| 314 | self.assertEqual( |
| 315 | (permissions.ANON_ROLE, project_pb2.ProjectState.LIVE, |
| 316 | project_pb2.ProjectAccess.ANYONE), |
| 317 | permissions._GetPermissionKey(None, self.live_project)) |
| 318 | |
| 319 | def testGetPermissionKey_ExpiredProject(self): |
| 320 | self.archived_project.delete_time = self.NOW |
| 321 | # In an expired project, the user's committe role does not count. |
| 322 | self.assertEqual( |
| 323 | (permissions.USER_ROLE, project_pb2.ProjectState.ARCHIVED, |
| 324 | project_pb2.ProjectAccess.ANYONE), |
| 325 | permissions._GetPermissionKey( |
| 326 | self.COMMITTER_USER_ID, self.archived_project, |
| 327 | expired_before=self.NOW + 1)) |
| 328 | # If not expired yet, the user's committe role still counts. |
| 329 | self.assertEqual( |
| 330 | (permissions.COMMITTER_ROLE, project_pb2.ProjectState.ARCHIVED, |
| 331 | project_pb2.ProjectAccess.ANYONE), |
| 332 | permissions._GetPermissionKey( |
| 333 | self.COMMITTER_USER_ID, self.archived_project, |
| 334 | expired_before=self.NOW - 1)) |
| 335 | |
| 336 | def testGetPermissionKey_DefinedRoles(self): |
| 337 | self.assertEqual( |
| 338 | (permissions.OWNER_ROLE, project_pb2.ProjectState.LIVE, |
| 339 | project_pb2.ProjectAccess.ANYONE), |
| 340 | permissions._GetPermissionKey( |
| 341 | self.OWNER_USER_ID, self.live_project)) |
| 342 | self.assertEqual( |
| 343 | (permissions.COMMITTER_ROLE, project_pb2.ProjectState.LIVE, |
| 344 | project_pb2.ProjectAccess.ANYONE), |
| 345 | permissions._GetPermissionKey( |
| 346 | self.COMMITTER_USER_ID, self.live_project)) |
| 347 | self.assertEqual( |
| 348 | (permissions.CONTRIBUTOR_ROLE, project_pb2.ProjectState.LIVE, |
| 349 | project_pb2.ProjectAccess.ANYONE), |
| 350 | permissions._GetPermissionKey( |
| 351 | self.CONTRIB_USER_ID, self.live_project)) |
| 352 | |
| 353 | def testGetPermissionKey_Nonmember(self): |
| 354 | self.assertEqual( |
| 355 | (permissions.USER_ROLE, project_pb2.ProjectState.LIVE, |
| 356 | project_pb2.ProjectAccess.ANYONE), |
| 357 | permissions._GetPermissionKey( |
| 358 | 999, self.live_project)) |
| 359 | |
| 360 | def testPermissionsImmutable(self): |
| 361 | self.assertTrue(isinstance( |
| 362 | permissions.EMPTY_PERMISSIONSET.perm_names, frozenset)) |
| 363 | self.assertTrue(isinstance( |
| 364 | permissions.READ_ONLY_PERMISSIONSET.perm_names, frozenset)) |
| 365 | self.assertTrue(isinstance( |
| 366 | permissions.COMMITTER_ACTIVE_PERMISSIONSET.perm_names, frozenset)) |
| 367 | self.assertTrue(isinstance( |
| 368 | permissions.OWNER_ACTIVE_PERMISSIONSET.perm_names, frozenset)) |
| 369 | |
| 370 | def testGetExtraPerms(self): |
| 371 | project = project_pb2.Project() |
| 372 | project.committer_ids.append(222) |
| 373 | # User 1 is a former member with left-over extra perms that don't count. |
| 374 | project.extra_perms.append(project_pb2.Project.ExtraPerms( |
| 375 | member_id=111, perms=['a', 'b', 'c'])) |
| 376 | project.extra_perms.append(project_pb2.Project.ExtraPerms( |
| 377 | member_id=222, perms=['a', 'b', 'c'])) |
| 378 | |
| 379 | self.assertListEqual( |
| 380 | [], |
| 381 | permissions.GetExtraPerms(project, 111)) |
| 382 | self.assertListEqual( |
| 383 | ['a', 'b', 'c'], |
| 384 | permissions.GetExtraPerms(project, 222)) |
| 385 | self.assertListEqual( |
| 386 | [], |
| 387 | permissions.GetExtraPerms(project, 333)) |
| 388 | |
| 389 | def testCanDeleteComment_NoPermissionSet(self): |
| 390 | """Test that if no PermissionSet is given, we can't delete comments.""" |
| 391 | comment = tracker_pb2.IssueComment() |
| 392 | commenter = user_pb2.User() |
| 393 | # If no PermissionSet is given, the user cannot delete the comment. |
| 394 | self.assertFalse(permissions.CanDeleteComment( |
| 395 | comment, commenter, 111, None)) |
| 396 | # Same, with no user specified. |
| 397 | self.assertFalse(permissions.CanDeleteComment( |
| 398 | comment, commenter, framework_constants.NO_USER_SPECIFIED, None)) |
| 399 | |
| 400 | def testCanDeleteComment_AnonUsersCannotDelete(self): |
| 401 | """Test that anon users can't delete comments.""" |
| 402 | comment = tracker_pb2.IssueComment() |
| 403 | commenter = user_pb2.User() |
| 404 | perms = permissions.PermissionSet([permissions.DELETE_ANY]) |
| 405 | |
| 406 | # No logged in user, even with perms from somewhere. |
| 407 | self.assertFalse(permissions.CanDeleteComment( |
| 408 | comment, commenter, framework_constants.NO_USER_SPECIFIED, perms)) |
| 409 | |
| 410 | # No logged in user, even if artifact was already deleted. |
| 411 | comment.deleted_by = 111 |
| 412 | self.assertFalse(permissions.CanDeleteComment( |
| 413 | comment, commenter, framework_constants.NO_USER_SPECIFIED, perms)) |
| 414 | |
| 415 | def testCanDeleteComment_DeleteAny(self): |
| 416 | """Test that users with DeleteAny permission can delete any comment. |
| 417 | |
| 418 | Except for spam comments or comments by banned users. |
| 419 | """ |
| 420 | comment = tracker_pb2.IssueComment(user_id=111) |
| 421 | commenter = user_pb2.User() |
| 422 | perms = permissions.PermissionSet([permissions.DELETE_ANY]) |
| 423 | |
| 424 | # Users with DeleteAny permission can delete their own comments. |
| 425 | self.assertTrue(permissions.CanDeleteComment( |
| 426 | comment, commenter, 111, perms)) |
| 427 | |
| 428 | # And also comments by other users |
| 429 | comment.user_id = 999 |
| 430 | self.assertTrue(permissions.CanDeleteComment( |
| 431 | comment, commenter, 111, perms)) |
| 432 | |
| 433 | # As well as undelete comments they deleted. |
| 434 | comment.deleted_by = 111 |
| 435 | self.assertTrue(permissions.CanDeleteComment( |
| 436 | comment, commenter, 111, perms)) |
| 437 | |
| 438 | # Or that other users deleted. |
| 439 | comment.deleted_by = 222 |
| 440 | self.assertTrue(permissions.CanDeleteComment( |
| 441 | comment, commenter, 111, perms)) |
| 442 | |
| 443 | def testCanDeleteComment_DeleteOwn(self): |
| 444 | """Test that users with DeleteOwn permission can delete any comment. |
| 445 | |
| 446 | Except for spam comments or comments by banned users. |
| 447 | """ |
| 448 | comment = tracker_pb2.IssueComment(user_id=111) |
| 449 | commenter = user_pb2.User() |
| 450 | perms = permissions.PermissionSet([permissions.DELETE_OWN]) |
| 451 | |
| 452 | # Users with DeleteOwn permission can delete their own comments. |
| 453 | self.assertTrue(permissions.CanDeleteComment( |
| 454 | comment, commenter, 111, perms)) |
| 455 | |
| 456 | # But not comments by other users |
| 457 | comment.user_id = 999 |
| 458 | self.assertFalse(permissions.CanDeleteComment( |
| 459 | comment, commenter, 111, perms)) |
| 460 | |
| 461 | # They can undelete comments they deleted. |
| 462 | comment.user_id = 111 |
| 463 | comment.deleted_by = 111 |
| 464 | self.assertTrue(permissions.CanDeleteComment( |
| 465 | comment, commenter, 111, perms)) |
| 466 | |
| 467 | # But not comments that other users deleted. |
| 468 | comment.deleted_by = 222 |
| 469 | self.assertFalse(permissions.CanDeleteComment( |
| 470 | comment, commenter, 111, perms)) |
| 471 | |
| 472 | def testCanDeleteComment_CannotDeleteSpamComments(self): |
| 473 | """Test that nobody can (un)delete comments marked as spam.""" |
| 474 | comment = tracker_pb2.IssueComment(user_id=111, is_spam=True) |
| 475 | commenter = user_pb2.User() |
| 476 | |
| 477 | # Nobody can delete comments marked as spam. |
| 478 | self.assertFalse(permissions.CanDeleteComment( |
| 479 | comment, commenter, 111, |
| 480 | permissions.PermissionSet([permissions.DELETE_OWN]))) |
| 481 | self.assertFalse(permissions.CanDeleteComment( |
| 482 | comment, commenter, 222, |
| 483 | permissions.PermissionSet([permissions.DELETE_ANY]))) |
| 484 | |
| 485 | # Nobody can undelete comments marked as spam. |
| 486 | comment.deleted_by = 222 |
| 487 | self.assertFalse(permissions.CanDeleteComment( |
| 488 | comment, commenter, 111, |
| 489 | permissions.PermissionSet([permissions.DELETE_OWN]))) |
| 490 | self.assertFalse(permissions.CanDeleteComment( |
| 491 | comment, commenter, 222, |
| 492 | permissions.PermissionSet([permissions.DELETE_ANY]))) |
| 493 | |
| 494 | def testCanDeleteComment_CannotDeleteCommentsByBannedUser(self): |
| 495 | """Test that nobody can (un)delete comments by banned users.""" |
| 496 | comment = tracker_pb2.IssueComment(user_id=111) |
| 497 | commenter = user_pb2.User(banned='Some reason') |
| 498 | |
| 499 | # Nobody can delete comments by banned users. |
| 500 | self.assertFalse(permissions.CanDeleteComment( |
| 501 | comment, commenter, 111, |
| 502 | permissions.PermissionSet([permissions.DELETE_OWN]))) |
| 503 | self.assertFalse(permissions.CanDeleteComment( |
| 504 | comment, commenter, 222, |
| 505 | permissions.PermissionSet([permissions.DELETE_ANY]))) |
| 506 | |
| 507 | # Nobody can undelete comments by banned users. |
| 508 | comment.deleted_by = 222 |
| 509 | self.assertFalse(permissions.CanDeleteComment( |
| 510 | comment, commenter, 111, |
| 511 | permissions.PermissionSet([permissions.DELETE_OWN]))) |
| 512 | self.assertFalse(permissions.CanDeleteComment( |
| 513 | comment, commenter, 222, |
| 514 | permissions.PermissionSet([permissions.DELETE_ANY]))) |
| 515 | |
| 516 | def testCanFlagComment_FlagSpamCanReport(self): |
| 517 | """Test that users with FlagSpam permissions can report comments.""" |
| 518 | comment = tracker_pb2.IssueComment() |
| 519 | commenter = user_pb2.User() |
| 520 | |
| 521 | can_flag, is_flagged = permissions.CanFlagComment( |
| 522 | comment, commenter, [], 111, |
| 523 | permissions.PermissionSet([permissions.FLAG_SPAM])) |
| 524 | |
| 525 | self.assertTrue(can_flag) |
| 526 | self.assertFalse(is_flagged) |
| 527 | |
| 528 | def testCanFlagComment_FlagSpamCanUnReportOwn(self): |
| 529 | """Test that users with FlagSpam permission can un-report comments they |
| 530 | previously reported.""" |
| 531 | comment = tracker_pb2.IssueComment() |
| 532 | commenter = user_pb2.User() |
| 533 | |
| 534 | can_flag, is_flagged = permissions.CanFlagComment( |
| 535 | comment, commenter, [111], 111, |
| 536 | permissions.PermissionSet([permissions.FLAG_SPAM])) |
| 537 | |
| 538 | self.assertTrue(can_flag) |
| 539 | self.assertTrue(is_flagged) |
| 540 | |
| 541 | def testCanFlagComment_FlagSpamCannotUnReportOthers(self): |
| 542 | """Test that users with FlagSpam permission doesn't know if other users have |
| 543 | reported a comment as spam.""" |
| 544 | comment = tracker_pb2.IssueComment() |
| 545 | commenter = user_pb2.User() |
| 546 | |
| 547 | can_flag, is_flagged = permissions.CanFlagComment( |
| 548 | comment, commenter, [222], 111, |
| 549 | permissions.PermissionSet([permissions.FLAG_SPAM])) |
| 550 | |
| 551 | self.assertTrue(can_flag) |
| 552 | self.assertFalse(is_flagged) |
| 553 | |
| 554 | def testCanFlagComment_FlagSpamCannotUnFlag(self): |
| 555 | comment = tracker_pb2.IssueComment(is_spam=True) |
| 556 | commenter = user_pb2.User() |
| 557 | |
| 558 | can_flag, is_flagged = permissions.CanFlagComment( |
| 559 | comment, commenter, [111], 111, |
| 560 | permissions.PermissionSet([permissions.FLAG_SPAM])) |
| 561 | |
| 562 | self.assertFalse(can_flag) |
| 563 | self.assertTrue(is_flagged) |
| 564 | |
| 565 | def testCanFlagComment_VerdictSpamCanFlag(self): |
| 566 | """Test that users with FlagSpam permissions can flag comments.""" |
| 567 | comment = tracker_pb2.IssueComment() |
| 568 | commenter = user_pb2.User() |
| 569 | |
| 570 | can_flag, is_flagged = permissions.CanFlagComment( |
| 571 | comment, commenter, [], 111, |
| 572 | permissions.PermissionSet([permissions.VERDICT_SPAM])) |
| 573 | |
| 574 | self.assertTrue(can_flag) |
| 575 | self.assertFalse(is_flagged) |
| 576 | |
| 577 | def testCanFlagComment_VerdictSpamCanUnFlag(self): |
| 578 | """Test that users with FlagSpam permissions can un-flag comments.""" |
| 579 | comment = tracker_pb2.IssueComment(is_spam=True) |
| 580 | commenter = user_pb2.User() |
| 581 | |
| 582 | can_flag, is_flagged = permissions.CanFlagComment( |
| 583 | comment, commenter, [], 111, |
| 584 | permissions.PermissionSet([permissions.VERDICT_SPAM])) |
| 585 | |
| 586 | self.assertTrue(can_flag) |
| 587 | self.assertTrue(is_flagged) |
| 588 | |
| 589 | def testCanFlagComment_CannotFlagNoPermission(self): |
| 590 | """Test that users without permission cannot flag comments.""" |
| 591 | comment = tracker_pb2.IssueComment() |
| 592 | commenter = user_pb2.User() |
| 593 | |
| 594 | can_flag, is_flagged = permissions.CanFlagComment( |
| 595 | comment, commenter, [], 111, |
| 596 | permissions.PermissionSet([permissions.DELETE_ANY])) |
| 597 | |
| 598 | self.assertFalse(can_flag) |
| 599 | self.assertFalse(is_flagged) |
| 600 | |
| 601 | def testCanFlagComment_CannotUnFlagNoPermission(self): |
| 602 | """Test that users without permission cannot un-flag comments.""" |
| 603 | comment = tracker_pb2.IssueComment(is_spam=True) |
| 604 | commenter = user_pb2.User() |
| 605 | |
| 606 | can_flag, is_flagged = permissions.CanFlagComment( |
| 607 | comment, commenter, [], 111, |
| 608 | # Users need the VerdictSpam permission to be able to un-flag comments. |
| 609 | permissions.PermissionSet([ |
| 610 | permissions.DELETE_ANY, permissions.FLAG_SPAM])) |
| 611 | |
| 612 | self.assertFalse(can_flag) |
| 613 | self.assertTrue(is_flagged) |
| 614 | |
| 615 | def testCanFlagComment_CannotFlagCommentByBannedUser(self): |
| 616 | """Test that nobady can flag comments by banned users.""" |
| 617 | comment = tracker_pb2.IssueComment() |
| 618 | commenter = user_pb2.User(banned='Some reason') |
| 619 | |
| 620 | can_flag, is_flagged = permissions.CanFlagComment( |
| 621 | comment, commenter, [], 111, |
| 622 | permissions.PermissionSet([ |
| 623 | permissions.FLAG_SPAM, permissions.VERDICT_SPAM])) |
| 624 | |
| 625 | self.assertFalse(can_flag) |
| 626 | self.assertFalse(is_flagged) |
| 627 | |
| 628 | def testCanFlagComment_CannotUnFlagCommentByBannedUser(self): |
| 629 | """Test that nobady can un-flag comments by banned users.""" |
| 630 | comment = tracker_pb2.IssueComment(is_spam=True) |
| 631 | commenter = user_pb2.User(banned='Some reason') |
| 632 | |
| 633 | can_flag, is_flagged = permissions.CanFlagComment( |
| 634 | comment, commenter, [], 111, |
| 635 | permissions.PermissionSet([ |
| 636 | permissions.FLAG_SPAM, permissions.VERDICT_SPAM])) |
| 637 | |
| 638 | self.assertFalse(can_flag) |
| 639 | self.assertTrue(is_flagged) |
| 640 | |
| 641 | def testCanFlagComment_CanUnFlagDeletedSpamComment(self): |
| 642 | """Test that we can un-flag a deleted comment that is spam.""" |
| 643 | comment = tracker_pb2.IssueComment(is_spam=True, deleted_by=111) |
| 644 | commenter = user_pb2.User() |
| 645 | |
| 646 | can_flag, is_flagged = permissions.CanFlagComment( |
| 647 | comment, commenter, [], 222, |
| 648 | permissions.PermissionSet([permissions.VERDICT_SPAM])) |
| 649 | |
| 650 | self.assertTrue(can_flag) |
| 651 | self.assertTrue(is_flagged) |
| 652 | |
| 653 | def testCanFlagComment_CannotFlagDeletedComment(self): |
| 654 | """Test that nobody can flag a deleted comment that is not spam.""" |
| 655 | comment = tracker_pb2.IssueComment(deleted_by=111) |
| 656 | commenter = user_pb2.User() |
| 657 | |
| 658 | can_flag, is_flagged = permissions.CanFlagComment( |
| 659 | comment, commenter, [], 111, |
| 660 | permissions.PermissionSet([ |
| 661 | permissions.FLAG_SPAM, permissions.VERDICT_SPAM, |
| 662 | permissions.DELETE_ANY, permissions.DELETE_OWN])) |
| 663 | |
| 664 | self.assertFalse(can_flag) |
| 665 | self.assertFalse(is_flagged) |
| 666 | |
| 667 | def testCanViewComment_Normal(self): |
| 668 | """Test that we can view comments.""" |
| 669 | comment = tracker_pb2.IssueComment() |
| 670 | commenter = user_pb2.User() |
| 671 | # We assume that CanViewIssue was already called. There are no further |
| 672 | # restrictions to view this comment. |
| 673 | self.assertTrue(permissions.CanViewComment( |
| 674 | comment, commenter, 111, None)) |
| 675 | |
| 676 | def testCanViewComment_CannotViewCommentsByBannedUser(self): |
| 677 | """Test that nobody can view comments by banned users.""" |
| 678 | comment = tracker_pb2.IssueComment(user_id=111) |
| 679 | commenter = user_pb2.User(banned='Some reason') |
| 680 | |
| 681 | # Nobody can view comments by banned users. |
| 682 | self.assertFalse(permissions.CanViewComment( |
| 683 | comment, commenter, 111, permissions.ADMIN_PERMISSIONSET)) |
| 684 | |
| 685 | def testCanViewComment_OnlyModeratorsCanViewSpamComments(self): |
| 686 | """Test that only users with VerdictSpam can view spam comments.""" |
| 687 | comment = tracker_pb2.IssueComment(user_id=111, is_spam=True) |
| 688 | commenter = user_pb2.User() |
| 689 | |
| 690 | # Users with VerdictSpam permission can view comments marked as spam. |
| 691 | self.assertTrue(permissions.CanViewComment( |
| 692 | comment, commenter, 222, |
| 693 | permissions.PermissionSet([permissions.VERDICT_SPAM]))) |
| 694 | |
| 695 | # Other users cannot view comments marked as spam, even if it is their own |
| 696 | # comment. |
| 697 | self.assertFalse(permissions.CanViewComment( |
| 698 | comment, commenter, 111, |
| 699 | permissions.PermissionSet([ |
| 700 | permissions.FLAG_SPAM, permissions.DELETE_ANY, |
| 701 | permissions.DELETE_OWN]))) |
| 702 | |
| 703 | def testCanViewComment_DeletedComment(self): |
| 704 | """Test that for deleted comments, only the users that can undelete it can |
| 705 | view it. |
| 706 | """ |
| 707 | comment = tracker_pb2.IssueComment(user_id=111, deleted_by=222) |
| 708 | commenter = user_pb2.User() |
| 709 | |
| 710 | # Users with DeleteAny permission can view all deleted comments. |
| 711 | self.assertTrue(permissions.CanViewComment( |
| 712 | comment, commenter, 333, |
| 713 | permissions.PermissionSet([permissions.DELETE_ANY]))) |
| 714 | |
| 715 | # Users with DeleteOwn permissions can only see their own comments if they |
| 716 | # deleted them. |
| 717 | comment.user_id = comment.deleted_by = 333 |
| 718 | self.assertTrue(permissions.CanViewComment( |
| 719 | comment, commenter, 333, |
| 720 | permissions.PermissionSet([permissions.DELETE_OWN]))) |
| 721 | |
| 722 | # But not comments they didn't delete. |
| 723 | comment.deleted_by = 111 |
| 724 | self.assertFalse(permissions.CanViewComment( |
| 725 | comment, commenter, 333, |
| 726 | permissions.PermissionSet([permissions.DELETE_OWN]))) |
| 727 | |
| 728 | def testCanViewInboundMessage(self): |
| 729 | comment = tracker_pb2.IssueComment(user_id=111) |
| 730 | |
| 731 | # Users can view their own inbound messages |
| 732 | self.assertTrue(permissions.CanViewInboundMessage( |
| 733 | comment, 111, permissions.EMPTY_PERMISSIONSET)) |
| 734 | |
| 735 | # Users with the ViewInboundMessages permissions can view inbound messages. |
| 736 | self.assertTrue(permissions.CanViewInboundMessage( |
| 737 | comment, 333, |
| 738 | permissions.PermissionSet([permissions.VIEW_INBOUND_MESSAGES]))) |
| 739 | |
| 740 | # Other users cannot view inbound messages. |
| 741 | self.assertFalse(permissions.CanViewInboundMessage( |
| 742 | comment, 333, |
| 743 | permissions.PermissionSet([permissions.VIEW]))) |
| 744 | |
| 745 | def testCanViewNormalArifact(self): |
| 746 | # Anyone can view a non-restricted artifact. |
| 747 | self.assertTrue(permissions.CanView( |
| 748 | {111}, permissions.READ_ONLY_PERMISSIONSET, |
| 749 | self.live_project, [])) |
| 750 | |
| 751 | def testCanCreateProject_NoPerms(self): |
| 752 | """Signed out users cannot create projects.""" |
| 753 | self.assertFalse(permissions.CanCreateProject( |
| 754 | permissions.EMPTY_PERMISSIONSET)) |
| 755 | |
| 756 | self.assertFalse(permissions.CanCreateProject( |
| 757 | permissions.READ_ONLY_PERMISSIONSET)) |
| 758 | |
| 759 | def testCanCreateProject_Admin(self): |
| 760 | """Site admins can create projects.""" |
| 761 | self.assertTrue(permissions.CanCreateProject( |
| 762 | permissions.ADMIN_PERMISSIONSET)) |
| 763 | |
| 764 | def testCanCreateProject_RegularUser(self): |
| 765 | """Signed in non-admins can create a project if settings allow ANYONE.""" |
| 766 | try: |
| 767 | orig_restriction = settings.project_creation_restriction |
| 768 | ANYONE = site_pb2.UserTypeRestriction.ANYONE |
| 769 | ADMIN_ONLY = site_pb2.UserTypeRestriction.ADMIN_ONLY |
| 770 | NO_ONE = site_pb2.UserTypeRestriction.NO_ONE |
| 771 | perms = permissions.PermissionSet([permissions.CREATE_PROJECT]) |
| 772 | |
| 773 | settings.project_creation_restriction = ANYONE |
| 774 | self.assertTrue(permissions.CanCreateProject(perms)) |
| 775 | |
| 776 | settings.project_creation_restriction = ADMIN_ONLY |
| 777 | self.assertFalse(permissions.CanCreateProject(perms)) |
| 778 | |
| 779 | settings.project_creation_restriction = NO_ONE |
| 780 | self.assertFalse(permissions.CanCreateProject(perms)) |
| 781 | self.assertFalse(permissions.CanCreateProject( |
| 782 | permissions.ADMIN_PERMISSIONSET)) |
| 783 | finally: |
| 784 | settings.project_creation_restriction = orig_restriction |
| 785 | |
| 786 | def testCanCreateGroup_AnyoneWithCreateGroup(self): |
| 787 | orig_setting = settings.group_creation_restriction |
| 788 | try: |
| 789 | settings.group_creation_restriction = site_pb2.UserTypeRestriction.ANYONE |
| 790 | self.assertTrue(permissions.CanCreateGroup( |
| 791 | permissions.PermissionSet([permissions.CREATE_GROUP]))) |
| 792 | self.assertFalse(permissions.CanCreateGroup( |
| 793 | permissions.PermissionSet([]))) |
| 794 | finally: |
| 795 | settings.group_creation_restriction = orig_setting |
| 796 | |
| 797 | def testCanCreateGroup_AdminOnly(self): |
| 798 | orig_setting = settings.group_creation_restriction |
| 799 | try: |
| 800 | ADMIN_ONLY = site_pb2.UserTypeRestriction.ADMIN_ONLY |
| 801 | settings.group_creation_restriction = ADMIN_ONLY |
| 802 | self.assertTrue(permissions.CanCreateGroup( |
| 803 | permissions.PermissionSet([permissions.ADMINISTER_SITE]))) |
| 804 | self.assertFalse(permissions.CanCreateGroup( |
| 805 | permissions.PermissionSet([permissions.CREATE_GROUP]))) |
| 806 | self.assertFalse(permissions.CanCreateGroup( |
| 807 | permissions.PermissionSet([]))) |
| 808 | finally: |
| 809 | settings.group_creation_restriction = orig_setting |
| 810 | |
| 811 | def testCanCreateGroup_UnspecifiedSetting(self): |
| 812 | orig_setting = settings.group_creation_restriction |
| 813 | try: |
| 814 | settings.group_creation_restriction = None |
| 815 | self.assertFalse(permissions.CanCreateGroup( |
| 816 | permissions.PermissionSet([permissions.ADMINISTER_SITE]))) |
| 817 | self.assertFalse(permissions.CanCreateGroup( |
| 818 | permissions.PermissionSet([permissions.CREATE_GROUP]))) |
| 819 | self.assertFalse(permissions.CanCreateGroup( |
| 820 | permissions.PermissionSet([]))) |
| 821 | finally: |
| 822 | settings.group_creation_restriction = orig_setting |
| 823 | |
| 824 | def testCanEditGroup_HasPerm(self): |
| 825 | self.assertTrue(permissions.CanEditGroup( |
| 826 | permissions.PermissionSet([permissions.EDIT_GROUP]), None, None)) |
| 827 | |
| 828 | def testCanEditGroup_IsOwner(self): |
| 829 | self.assertTrue(permissions.CanEditGroup( |
| 830 | permissions.PermissionSet([]), {111}, {111})) |
| 831 | |
| 832 | def testCanEditGroup_Otherwise(self): |
| 833 | self.assertFalse(permissions.CanEditGroup( |
| 834 | permissions.PermissionSet([]), {111}, {222})) |
| 835 | |
| 836 | def testCanViewGroupMembers_HasPerm(self): |
| 837 | self.assertTrue(permissions.CanViewGroupMembers( |
| 838 | permissions.PermissionSet([permissions.VIEW_GROUP]), |
| 839 | None, None, None, None, None)) |
| 840 | |
| 841 | def testCanViewGroupMembers_IsMemberOfFriendProject(self): |
| 842 | group_settings = usergroup_pb2.MakeSettings('owners', friend_projects=[890]) |
| 843 | self.assertFalse(permissions.CanViewGroupMembers( |
| 844 | permissions.PermissionSet([]), |
| 845 | {111}, group_settings, {222}, {333}, {789})) |
| 846 | self.assertTrue(permissions.CanViewGroupMembers( |
| 847 | permissions.PermissionSet([]), |
| 848 | {111}, group_settings, {222}, {333}, {789, 890})) |
| 849 | |
| 850 | def testCanViewGroupMembers_VisibleToOwner(self): |
| 851 | group_settings = usergroup_pb2.MakeSettings('owners') |
| 852 | self.assertFalse(permissions.CanViewGroupMembers( |
| 853 | permissions.PermissionSet([]), |
| 854 | {111}, group_settings, {222}, {333}, {789})) |
| 855 | self.assertFalse(permissions.CanViewGroupMembers( |
| 856 | permissions.PermissionSet([]), |
| 857 | {222}, group_settings, {222}, {333}, {789})) |
| 858 | self.assertTrue(permissions.CanViewGroupMembers( |
| 859 | permissions.PermissionSet([]), |
| 860 | {333}, group_settings, {222}, {333}, {789})) |
| 861 | |
| 862 | def testCanViewGroupMembers_IsVisibleToMember(self): |
| 863 | group_settings = usergroup_pb2.MakeSettings('members') |
| 864 | self.assertFalse(permissions.CanViewGroupMembers( |
| 865 | permissions.PermissionSet([]), |
| 866 | {111}, group_settings, {222}, {333}, {789})) |
| 867 | self.assertTrue(permissions.CanViewGroupMembers( |
| 868 | permissions.PermissionSet([]), |
| 869 | {222}, group_settings, {222}, {333}, {789})) |
| 870 | self.assertTrue(permissions.CanViewGroupMembers( |
| 871 | permissions.PermissionSet([]), |
| 872 | {333}, group_settings, {222}, {333}, {789})) |
| 873 | |
| 874 | def testCanViewGroupMembers_AnyoneCanView(self): |
| 875 | group_settings = usergroup_pb2.MakeSettings('anyone') |
| 876 | self.assertTrue(permissions.CanViewGroupMembers( |
| 877 | permissions.PermissionSet([]), |
| 878 | {111}, group_settings, {222}, {333}, {789})) |
| 879 | |
| 880 | def testIsBanned_AnonUser(self): |
| 881 | user_view = framework_views.StuffUserView(None, None, True) |
| 882 | self.assertFalse(permissions.IsBanned(None, user_view)) |
| 883 | |
| 884 | def testIsBanned_NormalUser(self): |
| 885 | user = user_pb2.User() |
| 886 | user_view = framework_views.StuffUserView(None, None, True) |
| 887 | self.assertFalse(permissions.IsBanned(user, user_view)) |
| 888 | |
| 889 | def testIsBanned_BannedUser(self): |
| 890 | user = user_pb2.User() |
| 891 | user.banned = 'spammer' |
| 892 | user_view = framework_views.StuffUserView(None, None, True) |
| 893 | self.assertTrue(permissions.IsBanned(user, user_view)) |
| 894 | |
| 895 | def testIsBanned_BadDomainUser(self): |
| 896 | user = user_pb2.User() |
| 897 | self.assertFalse(permissions.IsBanned(user, None)) |
| 898 | |
| 899 | user_view = framework_views.StuffUserView(None, None, True) |
| 900 | user_view.domain = 'spammer.com' |
| 901 | self.assertFalse(permissions.IsBanned(user, user_view)) |
| 902 | |
| 903 | orig_banned_user_domains = settings.banned_user_domains |
| 904 | settings.banned_user_domains = ['spammer.com', 'phisher.com'] |
| 905 | self.assertTrue(permissions.IsBanned(user, user_view)) |
| 906 | settings.banned_user_domains = orig_banned_user_domains |
| 907 | |
| 908 | def testIsBanned_PlusAddressUser(self): |
| 909 | """We don't allow users who have + in their email address.""" |
| 910 | user = user_pb2.User(email='user@example.com') |
| 911 | self.assertFalse(permissions.IsBanned(user, None)) |
| 912 | |
| 913 | user.email = 'user+shadystuff@example.com' |
| 914 | self.assertTrue(permissions.IsBanned(user, None)) |
| 915 | |
| 916 | def testCanExpungeUser_Admin(self): |
| 917 | mr = testing_helpers.MakeMonorailRequest() |
| 918 | mr.perms = permissions.ADMIN_PERMISSIONSET |
| 919 | self.assertTrue(permissions.CanExpungeUsers(mr)) |
| 920 | |
| 921 | def testGetCustomPermissions(self): |
| 922 | project = project_pb2.Project() |
| 923 | self.assertListEqual([], permissions.GetCustomPermissions(project)) |
| 924 | |
| 925 | project.extra_perms.append(project_pb2.Project.ExtraPerms( |
| 926 | perms=['Core', 'Elite', 'Gold'])) |
| 927 | self.assertListEqual(['Core', 'Elite', 'Gold'], |
| 928 | permissions.GetCustomPermissions(project)) |
| 929 | |
| 930 | project.extra_perms.append(project_pb2.Project.ExtraPerms( |
| 931 | perms=['Silver', 'Gold', 'Bronze'])) |
| 932 | self.assertListEqual(['Bronze', 'Core', 'Elite', 'Gold', 'Silver'], |
| 933 | permissions.GetCustomPermissions(project)) |
| 934 | |
| 935 | # View is not returned because it is a starndard permission. |
| 936 | project.extra_perms.append(project_pb2.Project.ExtraPerms( |
| 937 | perms=['Bronze', permissions.VIEW])) |
| 938 | self.assertListEqual(['Bronze', 'Core', 'Elite', 'Gold', 'Silver'], |
| 939 | permissions.GetCustomPermissions(project)) |
| 940 | |
| 941 | def testUserCanViewProject(self): |
| 942 | self.mox.StubOutWithMock(time, 'time') |
| 943 | for _ in range(8): |
| 944 | time.time().AndReturn(self.NOW) |
| 945 | self.mox.ReplayAll() |
| 946 | |
| 947 | self.assertTrue(permissions.UserCanViewProject( |
| 948 | self.member, {self.COMMITTER_USER_ID}, self.live_project)) |
| 949 | self.assertTrue(permissions.UserCanViewProject( |
| 950 | None, None, self.live_project)) |
| 951 | |
| 952 | self.archived_project.delete_time = self.NOW + 1 |
| 953 | self.assertFalse(permissions.UserCanViewProject( |
| 954 | None, None, self.archived_project)) |
| 955 | self.assertTrue(permissions.UserCanViewProject( |
| 956 | self.owner, {self.OWNER_USER_ID}, self.archived_project)) |
| 957 | self.assertTrue(permissions.UserCanViewProject( |
| 958 | self.site_admin, {self.SITE_ADMIN_USER_ID}, |
| 959 | self.archived_project)) |
| 960 | |
| 961 | self.archived_project.delete_time = self.NOW - 1 |
| 962 | self.assertFalse(permissions.UserCanViewProject( |
| 963 | None, None, self.archived_project)) |
| 964 | self.assertFalse(permissions.UserCanViewProject( |
| 965 | self.owner, {self.OWNER_USER_ID}, self.archived_project)) |
| 966 | self.assertTrue(permissions.UserCanViewProject( |
| 967 | self.site_admin, {self.SITE_ADMIN_USER_ID}, |
| 968 | self.archived_project)) |
| 969 | |
| 970 | self.mox.VerifyAll() |
| 971 | |
| 972 | def CheckExpired(self, state, expected_to_be_reapable): |
| 973 | proj = project_pb2.Project() |
| 974 | proj.state = state |
| 975 | proj.delete_time = self.NOW + 1 |
| 976 | self.assertFalse(permissions.IsExpired(proj)) |
| 977 | |
| 978 | proj.delete_time = self.NOW - 1 |
| 979 | self.assertEqual(expected_to_be_reapable, permissions.IsExpired(proj)) |
| 980 | |
| 981 | proj.delete_time = self.NOW - 1 |
| 982 | self.assertFalse(permissions.IsExpired(proj, expired_before=self.NOW - 2)) |
| 983 | |
| 984 | def testIsExpired_Live(self): |
| 985 | self.CheckExpired(project_pb2.ProjectState.LIVE, False) |
| 986 | |
| 987 | def testIsExpired_Archived(self): |
| 988 | self.mox.StubOutWithMock(time, 'time') |
| 989 | for _ in range(2): |
| 990 | time.time().AndReturn(self.NOW) |
| 991 | self.mox.ReplayAll() |
| 992 | |
| 993 | self.CheckExpired(project_pb2.ProjectState.ARCHIVED, True) |
| 994 | |
| 995 | self.mox.VerifyAll() |
| 996 | |
| 997 | |
| 998 | class PermissionsCheckTest(unittest.TestCase): |
| 999 | |
| 1000 | def setUp(self): |
| 1001 | self.perms = permissions.PermissionSet(['a', 'b', 'c']) |
| 1002 | |
| 1003 | self.proj = project_pb2.Project() |
| 1004 | self.proj.committer_ids.append(111) |
| 1005 | self.proj.extra_perms.append(project_pb2.Project.ExtraPerms( |
| 1006 | member_id=111, perms=['d'])) |
| 1007 | |
| 1008 | # Note: z is an example of a perm that the user does not have. |
| 1009 | # Note: q is an example of an irrelevant perm that the user does not have. |
| 1010 | |
| 1011 | def DoCanUsePerm(self, perm, project='default', user_id=None, restrict=''): |
| 1012 | """Wrapper function to call CanUsePerm().""" |
| 1013 | if project == 'default': |
| 1014 | project = self.proj |
| 1015 | return self.perms.CanUsePerm( |
| 1016 | perm, {user_id or 111}, project, restrict.split()) |
| 1017 | |
| 1018 | def testHasPermNoRestrictions(self): |
| 1019 | self.assertTrue(self.DoCanUsePerm('a')) |
| 1020 | self.assertTrue(self.DoCanUsePerm('A')) |
| 1021 | self.assertFalse(self.DoCanUsePerm('z')) |
| 1022 | self.assertTrue(self.DoCanUsePerm('d')) |
| 1023 | self.assertFalse(self.DoCanUsePerm('d', user_id=222)) |
| 1024 | self.assertFalse(self.DoCanUsePerm('d', project=project_pb2.Project())) |
| 1025 | |
| 1026 | def testHasPermOperationRestrictions(self): |
| 1027 | self.assertTrue(self.DoCanUsePerm('a', restrict='Restrict-a-b')) |
| 1028 | self.assertTrue(self.DoCanUsePerm('a', restrict='Restrict-b-z')) |
| 1029 | self.assertTrue(self.DoCanUsePerm('a', restrict='Restrict-a-d')) |
| 1030 | self.assertTrue(self.DoCanUsePerm('d', restrict='Restrict-d-a')) |
| 1031 | self.assertTrue(self.DoCanUsePerm( |
| 1032 | 'd', restrict='Restrict-q-z Restrict-q-d Restrict-d-a')) |
| 1033 | |
| 1034 | self.assertFalse(self.DoCanUsePerm('a', restrict='Restrict-a-z')) |
| 1035 | self.assertFalse(self.DoCanUsePerm('d', restrict='Restrict-d-z')) |
| 1036 | self.assertFalse(self.DoCanUsePerm( |
| 1037 | 'd', restrict='Restrict-d-a Restrict-d-z')) |
| 1038 | |
| 1039 | def testHasPermOutsideProjectScope(self): |
| 1040 | self.assertTrue(self.DoCanUsePerm('a', project=None)) |
| 1041 | self.assertTrue(self.DoCanUsePerm( |
| 1042 | 'a', project=None, restrict='Restrict-a-c')) |
| 1043 | self.assertTrue(self.DoCanUsePerm( |
| 1044 | 'a', project=None, restrict='Restrict-q-z')) |
| 1045 | |
| 1046 | self.assertFalse(self.DoCanUsePerm('z', project=None)) |
| 1047 | self.assertFalse(self.DoCanUsePerm( |
| 1048 | 'a', project=None, restrict='Restrict-a-d')) |
| 1049 | |
| 1050 | |
| 1051 | class CanViewProjectContributorListTest(unittest.TestCase): |
| 1052 | |
| 1053 | def testCanViewProjectContributorList_NoProject(self): |
| 1054 | mr = testing_helpers.MakeMonorailRequest(path='/') |
| 1055 | self.assertFalse(permissions.CanViewContributorList(mr, mr.project)) |
| 1056 | |
| 1057 | def testCanViewProjectContributorList_NormalProject(self): |
| 1058 | project = project_pb2.Project() |
| 1059 | mr = testing_helpers.MakeMonorailRequest( |
| 1060 | path='/p/proj/', project=project) |
| 1061 | self.assertTrue(permissions.CanViewContributorList(mr, mr.project)) |
| 1062 | |
| 1063 | def testCanViewProjectContributorList_ProjectWithOptionSet(self): |
| 1064 | project = project_pb2.Project() |
| 1065 | project.only_owners_see_contributors = True |
| 1066 | |
| 1067 | for perms in [permissions.READ_ONLY_PERMISSIONSET, |
| 1068 | permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET, |
| 1069 | permissions.CONTRIBUTOR_INACTIVE_PERMISSIONSET]: |
| 1070 | mr = testing_helpers.MakeMonorailRequest( |
| 1071 | path='/p/proj/', project=project, perms=perms) |
| 1072 | self.assertFalse(permissions.CanViewContributorList(mr, mr.project)) |
| 1073 | |
| 1074 | for perms in [permissions.COMMITTER_ACTIVE_PERMISSIONSET, |
| 1075 | permissions.COMMITTER_INACTIVE_PERMISSIONSET, |
| 1076 | permissions.OWNER_ACTIVE_PERMISSIONSET, |
| 1077 | permissions.OWNER_INACTIVE_PERMISSIONSET, |
| 1078 | permissions.ADMIN_PERMISSIONSET]: |
| 1079 | mr = testing_helpers.MakeMonorailRequest( |
| 1080 | path='/p/proj/', project=project, perms=perms) |
| 1081 | self.assertTrue(permissions.CanViewContributorList(mr, mr.project)) |
| 1082 | |
| 1083 | |
| 1084 | class ShouldCheckForAbandonmentTest(unittest.TestCase): |
| 1085 | |
| 1086 | def setUp(self): |
| 1087 | self.mr = testing_helpers.Blank( |
| 1088 | project=project_pb2.Project(), |
| 1089 | auth=authdata.AuthData()) |
| 1090 | |
| 1091 | def testOwner(self): |
| 1092 | self.mr.auth.effective_ids = {111} |
| 1093 | self.mr.perms = permissions.OWNER_ACTIVE_PERMISSIONSET |
| 1094 | self.assertTrue(permissions.ShouldCheckForAbandonment(self.mr)) |
| 1095 | |
| 1096 | def testNonOwner(self): |
| 1097 | self.mr.auth.effective_ids = {222} |
| 1098 | self.mr.perms = permissions.COMMITTER_ACTIVE_PERMISSIONSET |
| 1099 | self.assertFalse(permissions.ShouldCheckForAbandonment(self.mr)) |
| 1100 | self.mr.perms = permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET |
| 1101 | self.assertFalse(permissions.ShouldCheckForAbandonment(self.mr)) |
| 1102 | self.mr.perms = permissions.USER_PERMISSIONSET |
| 1103 | self.assertFalse(permissions.ShouldCheckForAbandonment(self.mr)) |
| 1104 | self.mr.perms = permissions.EMPTY_PERMISSIONSET |
| 1105 | self.assertFalse(permissions.ShouldCheckForAbandonment(self.mr)) |
| 1106 | |
| 1107 | def testSiteAdmin(self): |
| 1108 | self.mr.auth.effective_ids = {111} |
| 1109 | self.mr.perms = permissions.ADMIN_PERMISSIONSET |
| 1110 | self.assertFalse(permissions.ShouldCheckForAbandonment(self.mr)) |
| 1111 | |
| 1112 | |
| 1113 | class RestrictionLabelsTest(unittest.TestCase): |
| 1114 | |
| 1115 | ORIG_SUMMARY = 'this is the orginal summary' |
| 1116 | ORIG_LABELS = ['one', 'two'] |
| 1117 | |
| 1118 | def testIsRestrictLabel(self): |
| 1119 | self.assertFalse(permissions.IsRestrictLabel('Usability')) |
| 1120 | self.assertTrue(permissions.IsRestrictLabel('Restrict-View-CoreTeam')) |
| 1121 | # Doing it again will test the cached results. |
| 1122 | self.assertFalse(permissions.IsRestrictLabel('Usability')) |
| 1123 | self.assertTrue(permissions.IsRestrictLabel('Restrict-View-CoreTeam')) |
| 1124 | |
| 1125 | self.assertFalse(permissions.IsRestrictLabel('Usability', perm='View')) |
| 1126 | self.assertTrue(permissions.IsRestrictLabel( |
| 1127 | 'Restrict-View-CoreTeam', perm='View')) |
| 1128 | |
| 1129 | # This one is a restriction label, but not the kind that we want. |
| 1130 | self.assertFalse(permissions.IsRestrictLabel( |
| 1131 | 'Restrict-View-CoreTeam', perm='Delete')) |
| 1132 | |
| 1133 | def testGetRestrictions_NoIssue(self): |
| 1134 | self.assertEqual([], permissions.GetRestrictions(None)) |
| 1135 | |
| 1136 | def testGetRestrictions_PermSpecified(self): |
| 1137 | """We can return restiction labels related to the given perm.""" |
| 1138 | art = fake.MakeTestIssue( |
| 1139 | 789, 1, self.ORIG_SUMMARY, 'New', 0, labels=self.ORIG_LABELS) |
| 1140 | self.assertEqual([], permissions.GetRestrictions(art, perm='view')) |
| 1141 | |
| 1142 | art = fake.MakeTestIssue( |
| 1143 | 789, 1, self.ORIG_SUMMARY, 'New', 0, |
| 1144 | labels=['Restrict-View-Core', 'Hot', |
| 1145 | 'Restrict-EditIssue-Commit', 'Restrict-EditIssue-Core']) |
| 1146 | self.assertEqual( |
| 1147 | ['restrict-view-core'], |
| 1148 | permissions.GetRestrictions(art, perm='view')) |
| 1149 | self.assertEqual( |
| 1150 | ['restrict-view-core'], |
| 1151 | permissions.GetRestrictions(art, perm='View')) |
| 1152 | self.assertEqual( |
| 1153 | ['restrict-editissue-commit', 'restrict-editissue-core'], |
| 1154 | permissions.GetRestrictions(art, perm='EditIssue')) |
| 1155 | |
| 1156 | def testGetRestrictions_NoPerm(self): |
| 1157 | art = fake.MakeTestIssue( |
| 1158 | 789, 1, self.ORIG_SUMMARY, 'New', 0, labels=self.ORIG_LABELS) |
| 1159 | self.assertEqual([], permissions.GetRestrictions(art)) |
| 1160 | |
| 1161 | art = fake.MakeTestIssue( |
| 1162 | 789, 1, self.ORIG_SUMMARY, 'New', 0, |
| 1163 | labels=['Restrict-MissingThirdPart', 'Hot']) |
| 1164 | self.assertEqual([], permissions.GetRestrictions(art)) |
| 1165 | |
| 1166 | art = fake.MakeTestIssue( |
| 1167 | 789, 1, self.ORIG_SUMMARY, 'New', 0, |
| 1168 | labels=['Restrict-View-Core', 'Hot']) |
| 1169 | self.assertEqual(['restrict-view-core'], permissions.GetRestrictions(art)) |
| 1170 | |
| 1171 | art = fake.MakeTestIssue( |
| 1172 | 789, 1, self.ORIG_SUMMARY, 'New', 0, |
| 1173 | labels=['Restrict-View-Core', 'Hot'], |
| 1174 | derived_labels=['Color-Red', 'Restrict-EditIssue-GoldMembers']) |
| 1175 | self.assertEqual( |
| 1176 | ['restrict-view-core', 'restrict-editissue-goldmembers'], |
| 1177 | permissions.GetRestrictions(art)) |
| 1178 | |
| 1179 | art = fake.MakeTestIssue( |
| 1180 | 789, 1, self.ORIG_SUMMARY, 'New', 0, |
| 1181 | labels=['restrict-view-core', 'hot'], |
| 1182 | derived_labels=['Color-Red', 'RESTRICT-EDITISSUE-GOLDMEMBERS']) |
| 1183 | self.assertEqual( |
| 1184 | ['restrict-view-core', 'restrict-editissue-goldmembers'], |
| 1185 | permissions.GetRestrictions(art)) |
| 1186 | |
| 1187 | |
| 1188 | REPORTER_ID = 111 |
| 1189 | OWNER_ID = 222 |
| 1190 | CC_ID = 333 |
| 1191 | OTHER_ID = 444 |
| 1192 | APPROVER_ID = 555 |
| 1193 | |
| 1194 | |
| 1195 | class IssuePermissionsTest(unittest.TestCase): |
| 1196 | |
| 1197 | REGULAR_ISSUE = tracker_pb2.Issue() |
| 1198 | REGULAR_ISSUE.reporter_id = REPORTER_ID |
| 1199 | |
| 1200 | DELETED_ISSUE = tracker_pb2.Issue() |
| 1201 | DELETED_ISSUE.deleted = True |
| 1202 | DELETED_ISSUE.reporter_id = REPORTER_ID |
| 1203 | |
| 1204 | RESTRICTED_ISSUE = tracker_pb2.Issue() |
| 1205 | RESTRICTED_ISSUE.reporter_id = REPORTER_ID |
| 1206 | RESTRICTED_ISSUE.owner_id = OWNER_ID |
| 1207 | RESTRICTED_ISSUE.cc_ids.append(CC_ID) |
| 1208 | RESTRICTED_ISSUE.approval_values.append( |
| 1209 | tracker_pb2.ApprovalValue(approver_ids=[APPROVER_ID]) |
| 1210 | ) |
| 1211 | RESTRICTED_ISSUE.labels.append('Restrict-View-Commit') |
| 1212 | |
| 1213 | RESTRICTED_ISSUE2 = tracker_pb2.Issue() |
| 1214 | RESTRICTED_ISSUE2.reporter_id = REPORTER_ID |
| 1215 | # RESTRICTED_ISSUE2 has no owner |
| 1216 | RESTRICTED_ISSUE2.cc_ids.append(CC_ID) |
| 1217 | RESTRICTED_ISSUE2.labels.append('Restrict-View-Commit') |
| 1218 | |
| 1219 | RESTRICTED_ISSUE3 = tracker_pb2.Issue() |
| 1220 | RESTRICTED_ISSUE3.reporter_id = REPORTER_ID |
| 1221 | RESTRICTED_ISSUE3.owner_id = OWNER_ID |
| 1222 | # Restrict to a permission that no one has. |
| 1223 | RESTRICTED_ISSUE3.labels.append('Restrict-EditIssue-Foo') |
| 1224 | |
| 1225 | PROJECT = project_pb2.Project() |
| 1226 | |
| 1227 | ADMIN_PERMS = permissions.ADMIN_PERMISSIONSET |
| 1228 | PERMS = permissions.EMPTY_PERMISSIONSET |
| 1229 | |
| 1230 | def testUpdateIssuePermissions_Normal(self): |
| 1231 | perms = permissions.UpdateIssuePermissions( |
| 1232 | permissions.COMMITTER_ACTIVE_PERMISSIONSET, self.PROJECT, |
| 1233 | self.REGULAR_ISSUE, {}) |
| 1234 | |
| 1235 | self.assertEqual( |
| 1236 | ['addissuecomment', |
| 1237 | 'commit', |
| 1238 | 'createissue', |
| 1239 | 'deleteown', |
| 1240 | 'editissue', |
| 1241 | 'flagspam', |
| 1242 | 'setstar', |
| 1243 | 'verdictspam', |
| 1244 | 'view', |
| 1245 | 'viewcontributorlist', |
| 1246 | 'viewinboundmessages', |
| 1247 | 'viewquota'], |
| 1248 | sorted(perms.perm_names)) |
| 1249 | |
| 1250 | def testUpdateIssuePermissions_FromConfig(self): |
| 1251 | config = tracker_pb2.ProjectIssueConfig( |
| 1252 | field_defs=[tracker_pb2.FieldDef(field_id=123, grants_perm='Granted')]) |
| 1253 | issue = tracker_pb2.Issue( |
| 1254 | field_values=[tracker_pb2.FieldValue(field_id=123, user_id=111)]) |
| 1255 | perms = permissions.UpdateIssuePermissions( |
| 1256 | permissions.USER_PERMISSIONSET, self.PROJECT, issue, {111}, |
| 1257 | config=config) |
| 1258 | self.assertIn('granted', perms.perm_names) |
| 1259 | |
| 1260 | def testUpdateIssuePermissions_ExtraPerms(self): |
| 1261 | project = project_pb2.Project() |
| 1262 | project.committer_ids.append(999) |
| 1263 | project.extra_perms.append( |
| 1264 | project_pb2.Project.ExtraPerms(member_id=999, perms=['EditIssue'])) |
| 1265 | perms = permissions.UpdateIssuePermissions( |
| 1266 | permissions.USER_PERMISSIONSET, project, |
| 1267 | self.REGULAR_ISSUE, {999}) |
| 1268 | self.assertIn('editissue', perms.perm_names) |
| 1269 | |
| 1270 | def testUpdateIssuePermissions_ExtraPermsAreSubjectToRestrictions(self): |
| 1271 | project = project_pb2.Project() |
| 1272 | project.committer_ids.append(999) |
| 1273 | project.extra_perms.append( |
| 1274 | project_pb2.Project.ExtraPerms(member_id=999, perms=['EditIssue'])) |
| 1275 | perms = permissions.UpdateIssuePermissions( |
| 1276 | permissions.USER_PERMISSIONSET, project, |
| 1277 | self.RESTRICTED_ISSUE3, {999}) |
| 1278 | self.assertNotIn('editissue', perms.perm_names) |
| 1279 | |
| 1280 | def testUpdateIssuePermissions_GrantedPermsAreNotSubjectToRestrictions(self): |
| 1281 | perms = permissions.UpdateIssuePermissions( |
| 1282 | permissions.USER_PERMISSIONSET, self.PROJECT, self.RESTRICTED_ISSUE3, |
| 1283 | {}, granted_perms=['EditIssue']) |
| 1284 | self.assertIn('editissue', perms.perm_names) |
| 1285 | |
| 1286 | def testUpdateIssuePermissions_RespectConsiderRestrictions(self): |
| 1287 | perms = permissions.UpdateIssuePermissions( |
| 1288 | permissions.ADMIN_PERMISSIONSET, self.PROJECT, self.RESTRICTED_ISSUE3, |
| 1289 | {}) |
| 1290 | self.assertIn('editissue', perms.perm_names) |
| 1291 | |
| 1292 | def testUpdateIssuePermissions_RestrictionsAreConsideredIndividually(self): |
| 1293 | issue = tracker_pb2.Issue( |
| 1294 | labels=[ |
| 1295 | 'Restrict-Perm1-Perm2', |
| 1296 | 'Restrict-Perm2-Perm3']) |
| 1297 | perms = permissions.UpdateIssuePermissions( |
| 1298 | permissions.PermissionSet(['Perm1', 'Perm2', 'View']), |
| 1299 | self.PROJECT, issue, {}) |
| 1300 | self.assertIn('perm1', perms.perm_names) |
| 1301 | self.assertNotIn('perm2', perms.perm_names) |
| 1302 | |
| 1303 | def testUpdateIssuePermissions_DeletedNoPermissions(self): |
| 1304 | issue = tracker_pb2.Issue( |
| 1305 | labels=['Restrict-View-Foo'], |
| 1306 | deleted=True) |
| 1307 | perms = permissions.UpdateIssuePermissions( |
| 1308 | permissions.COMMITTER_ACTIVE_PERMISSIONSET, self.PROJECT, issue, {}) |
| 1309 | self.assertEqual([], sorted(perms.perm_names)) |
| 1310 | |
| 1311 | def testUpdateIssuePermissions_ViewDeleted(self): |
| 1312 | perms = permissions.UpdateIssuePermissions( |
| 1313 | permissions.COMMITTER_ACTIVE_PERMISSIONSET, self.PROJECT, |
| 1314 | self.DELETED_ISSUE, {}) |
| 1315 | self.assertEqual(['view'], sorted(perms.perm_names)) |
| 1316 | |
| 1317 | def testUpdateIssuePermissions_ViewAndDeleteDeleted(self): |
| 1318 | perms = permissions.UpdateIssuePermissions( |
| 1319 | permissions.OWNER_ACTIVE_PERMISSIONSET, self.PROJECT, |
| 1320 | self.DELETED_ISSUE, {}) |
| 1321 | self.assertEqual(['deleteissue', 'view'], sorted(perms.perm_names)) |
| 1322 | |
| 1323 | def testUpdateIssuePermissions_ViewRestrictions(self): |
| 1324 | perms = permissions.UpdateIssuePermissions( |
| 1325 | permissions.USER_PERMISSIONSET, self.PROJECT, self.RESTRICTED_ISSUE, {}) |
| 1326 | self.assertNotIn('view', perms.perm_names) |
| 1327 | |
| 1328 | def testUpdateIssuePermissions_RolesBypassViewRestrictions(self): |
| 1329 | for role in {OWNER_ID, REPORTER_ID, CC_ID, APPROVER_ID}: |
| 1330 | perms = permissions.UpdateIssuePermissions( |
| 1331 | permissions.USER_PERMISSIONSET, self.PROJECT, self.RESTRICTED_ISSUE, |
| 1332 | {role}) |
| 1333 | self.assertIn('view', perms.perm_names) |
| 1334 | |
| 1335 | def testUpdateIssuePermissions_RolesAllowViewingDeleted(self): |
| 1336 | issue = tracker_pb2.Issue( |
| 1337 | reporter_id=REPORTER_ID, |
| 1338 | owner_id=OWNER_ID, |
| 1339 | cc_ids=[CC_ID], |
| 1340 | approval_values=[tracker_pb2.ApprovalValue(approver_ids=[APPROVER_ID])], |
| 1341 | labels=['Restrict-View-Foo'], |
| 1342 | deleted=True) |
| 1343 | for role in {OWNER_ID, REPORTER_ID, CC_ID, APPROVER_ID}: |
| 1344 | perms = permissions.UpdateIssuePermissions( |
| 1345 | permissions.USER_PERMISSIONSET, self.PROJECT, issue, {role}) |
| 1346 | self.assertIn('view', perms.perm_names) |
| 1347 | |
| 1348 | def testUpdateIssuePermissions_GrantedViewPermission(self): |
| 1349 | perms = permissions.UpdateIssuePermissions( |
| 1350 | permissions.USER_PERMISSIONSET, self.PROJECT, self.RESTRICTED_ISSUE, |
| 1351 | {}, ['commit']) |
| 1352 | self.assertIn('view', perms.perm_names) |
| 1353 | |
| 1354 | def testUpdateIssuePermissions_EditRestrictions(self): |
| 1355 | perms = permissions.UpdateIssuePermissions( |
| 1356 | permissions.COMMITTER_ACTIVE_PERMISSIONSET, self.PROJECT, |
| 1357 | self.RESTRICTED_ISSUE3, {REPORTER_ID, CC_ID, APPROVER_ID}) |
| 1358 | self.assertNotIn('editissue', perms.perm_names) |
| 1359 | |
| 1360 | def testUpdateIssuePermissions_OwnerBypassEditRestrictions(self): |
| 1361 | perms = permissions.UpdateIssuePermissions( |
| 1362 | permissions.COMMITTER_ACTIVE_PERMISSIONSET, self.PROJECT, |
| 1363 | self.RESTRICTED_ISSUE3, {OWNER_ID}) |
| 1364 | self.assertIn('editissue', perms.perm_names) |
| 1365 | |
| 1366 | def testUpdateIssuePermissions_CustomPermissionGrantsEditPermission(self): |
| 1367 | project = project_pb2.Project() |
| 1368 | project.committer_ids.append(999) |
| 1369 | project.extra_perms.append( |
| 1370 | project_pb2.Project.ExtraPerms(member_id=999, perms=['Foo'])) |
| 1371 | perms = permissions.UpdateIssuePermissions( |
| 1372 | permissions.COMMITTER_ACTIVE_PERMISSIONSET, project, |
| 1373 | self.RESTRICTED_ISSUE3, {999}) |
| 1374 | self.assertIn('editissue', perms.perm_names) |
| 1375 | |
| 1376 | def testCanViewIssue_Deleted(self): |
| 1377 | self.assertFalse(permissions.CanViewIssue( |
| 1378 | {REPORTER_ID}, permissions.OWNER_ACTIVE_PERMISSIONSET, |
| 1379 | self.PROJECT, self.DELETED_ISSUE)) |
| 1380 | self.assertTrue(permissions.CanViewIssue( |
| 1381 | {REPORTER_ID}, permissions.OWNER_ACTIVE_PERMISSIONSET, |
| 1382 | self.PROJECT, self.DELETED_ISSUE, allow_viewing_deleted=True)) |
| 1383 | self.assertTrue(permissions.CanViewIssue( |
| 1384 | {REPORTER_ID}, permissions.OWNER_ACTIVE_PERMISSIONSET, |
| 1385 | self.PROJECT, self.REGULAR_ISSUE)) |
| 1386 | |
| 1387 | def testCanViewIssue_Regular(self): |
| 1388 | self.assertTrue(permissions.CanViewIssue( |
| 1389 | {REPORTER_ID}, permissions.OWNER_ACTIVE_PERMISSIONSET, |
| 1390 | self.PROJECT, self.REGULAR_ISSUE)) |
| 1391 | self.assertTrue(permissions.CanViewIssue( |
| 1392 | {REPORTER_ID}, permissions.COMMITTER_ACTIVE_PERMISSIONSET, |
| 1393 | self.PROJECT, self.REGULAR_ISSUE)) |
| 1394 | self.assertTrue(permissions.CanViewIssue( |
| 1395 | {REPORTER_ID}, |
| 1396 | permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET, |
| 1397 | self.PROJECT, self.REGULAR_ISSUE)) |
| 1398 | self.assertTrue(permissions.CanViewIssue( |
| 1399 | {REPORTER_ID}, permissions.USER_PERMISSIONSET, |
| 1400 | self.PROJECT, self.REGULAR_ISSUE)) |
| 1401 | self.assertTrue(permissions.CanViewIssue( |
| 1402 | {REPORTER_ID}, permissions.READ_ONLY_PERMISSIONSET, |
| 1403 | self.PROJECT, self.REGULAR_ISSUE)) |
| 1404 | self.assertTrue(permissions.CanViewIssue( |
| 1405 | set(), permissions.READ_ONLY_PERMISSIONSET, |
| 1406 | self.PROJECT, self.REGULAR_ISSUE)) |
| 1407 | |
| 1408 | def testCanViewIssue_Restricted(self): |
| 1409 | # Project owner can always view issue. |
| 1410 | self.assertTrue(permissions.CanViewIssue( |
| 1411 | {OTHER_ID}, permissions.OWNER_ACTIVE_PERMISSIONSET, |
| 1412 | self.PROJECT, self.RESTRICTED_ISSUE)) |
| 1413 | # Member can view because they have Commit perm. |
| 1414 | self.assertTrue(permissions.CanViewIssue( |
| 1415 | {OTHER_ID}, permissions.COMMITTER_ACTIVE_PERMISSIONSET, |
| 1416 | self.PROJECT, self.RESTRICTED_ISSUE)) |
| 1417 | # Contributors normally do not have Commit perm. |
| 1418 | self.assertFalse(permissions.CanViewIssue( |
| 1419 | {OTHER_ID}, permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET, |
| 1420 | self.PROJECT, self.RESTRICTED_ISSUE)) |
| 1421 | # Non-members do not have Commit perm. |
| 1422 | self.assertFalse(permissions.CanViewIssue( |
| 1423 | {OTHER_ID}, permissions.USER_PERMISSIONSET, |
| 1424 | self.PROJECT, self.RESTRICTED_ISSUE)) |
| 1425 | # Anon user's do not have Commit perm. |
| 1426 | self.assertFalse(permissions.CanViewIssue( |
| 1427 | set(), permissions.READ_ONLY_PERMISSIONSET, |
| 1428 | self.PROJECT, self.RESTRICTED_ISSUE)) |
| 1429 | |
| 1430 | def testCanViewIssue_RestrictedParticipants(self): |
| 1431 | # Reporter can always view issue |
| 1432 | self.assertTrue(permissions.CanViewIssue( |
| 1433 | {REPORTER_ID}, permissions.READ_ONLY_PERMISSIONSET, |
| 1434 | self.PROJECT, self.RESTRICTED_ISSUE)) |
| 1435 | # Issue owner can always view issue |
| 1436 | self.assertTrue(permissions.CanViewIssue( |
| 1437 | {OWNER_ID}, permissions.READ_ONLY_PERMISSIONSET, |
| 1438 | self.PROJECT, self.RESTRICTED_ISSUE)) |
| 1439 | # CC'd user can always view issue |
| 1440 | self.assertTrue(permissions.CanViewIssue( |
| 1441 | {CC_ID}, permissions.READ_ONLY_PERMISSIONSET, |
| 1442 | self.PROJECT, self.RESTRICTED_ISSUE)) |
| 1443 | # Non-participants cannot view issue if they don't have the needed perm. |
| 1444 | self.assertFalse(permissions.CanViewIssue( |
| 1445 | {OTHER_ID}, permissions.READ_ONLY_PERMISSIONSET, |
| 1446 | self.PROJECT, self.RESTRICTED_ISSUE)) |
| 1447 | # Anon user's do not have Commit perm. |
| 1448 | self.assertFalse(permissions.CanViewIssue( |
| 1449 | set(), permissions.READ_ONLY_PERMISSIONSET, |
| 1450 | self.PROJECT, self.RESTRICTED_ISSUE)) |
| 1451 | # Anon user's cannot match owner 0. |
| 1452 | self.assertFalse(permissions.CanViewIssue( |
| 1453 | set(), permissions.READ_ONLY_PERMISSIONSET, |
| 1454 | self.PROJECT, self.RESTRICTED_ISSUE2)) |
| 1455 | # Approvers can always view issue |
| 1456 | self.assertTrue(permissions.CanViewIssue( |
| 1457 | {APPROVER_ID}, permissions.READ_ONLY_PERMISSIONSET, |
| 1458 | self.PROJECT, self.RESTRICTED_ISSUE)) |
| 1459 | |
| 1460 | def testCannotViewIssueIfCannotViewProject(self): |
| 1461 | """Cross-project search should not be a backdoor to viewing issues.""" |
| 1462 | # Reporter cannot view issue if they not long have access to the project. |
| 1463 | self.assertFalse(permissions.CanViewIssue( |
| 1464 | {REPORTER_ID}, permissions.EMPTY_PERMISSIONSET, |
| 1465 | self.PROJECT, self.REGULAR_ISSUE)) |
| 1466 | # Issue owner cannot always view issue |
| 1467 | self.assertFalse(permissions.CanViewIssue( |
| 1468 | {OWNER_ID}, permissions.EMPTY_PERMISSIONSET, |
| 1469 | self.PROJECT, self.REGULAR_ISSUE)) |
| 1470 | # CC'd user cannot always view issue |
| 1471 | self.assertFalse(permissions.CanViewIssue( |
| 1472 | {CC_ID}, permissions.EMPTY_PERMISSIONSET, |
| 1473 | self.PROJECT, self.REGULAR_ISSUE)) |
| 1474 | # Non-participants cannot view issue if they don't have the needed perm. |
| 1475 | self.assertFalse(permissions.CanViewIssue( |
| 1476 | {OTHER_ID}, permissions.EMPTY_PERMISSIONSET, |
| 1477 | self.PROJECT, self.REGULAR_ISSUE)) |
| 1478 | # Anon user's do not have Commit perm. |
| 1479 | self.assertFalse(permissions.CanViewIssue( |
| 1480 | set(), permissions.EMPTY_PERMISSIONSET, self.PROJECT, |
| 1481 | self.REGULAR_ISSUE)) |
| 1482 | # Anon user's cannot match owner 0. |
| 1483 | self.assertFalse(permissions.CanViewIssue( |
| 1484 | set(), permissions.EMPTY_PERMISSIONSET, self.PROJECT, |
| 1485 | self.REGULAR_ISSUE)) |
| 1486 | |
| 1487 | def testCanEditIssue(self): |
| 1488 | # Anon users cannot edit issues. |
| 1489 | self.assertFalse(permissions.CanEditIssue( |
| 1490 | {}, permissions.READ_ONLY_PERMISSIONSET, |
| 1491 | self.PROJECT, self.REGULAR_ISSUE)) |
| 1492 | |
| 1493 | # Non-members and contributors cannot edit issues, |
| 1494 | # even if they reported them. |
| 1495 | self.assertFalse(permissions.CanEditIssue( |
| 1496 | {REPORTER_ID}, permissions.READ_ONLY_PERMISSIONSET, |
| 1497 | self.PROJECT, self.REGULAR_ISSUE)) |
| 1498 | self.assertFalse(permissions.CanEditIssue( |
| 1499 | {REPORTER_ID}, permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET, |
| 1500 | self.PROJECT, self.REGULAR_ISSUE)) |
| 1501 | |
| 1502 | # Project committers and project owners can edit issues, regardless |
| 1503 | # of their role in the issue. |
| 1504 | self.assertTrue(permissions.CanEditIssue( |
| 1505 | {REPORTER_ID}, permissions.COMMITTER_ACTIVE_PERMISSIONSET, |
| 1506 | self.PROJECT, self.REGULAR_ISSUE)) |
| 1507 | self.assertTrue(permissions.CanEditIssue( |
| 1508 | {REPORTER_ID}, permissions.OWNER_ACTIVE_PERMISSIONSET, |
| 1509 | self.PROJECT, self.REGULAR_ISSUE)) |
| 1510 | self.assertTrue(permissions.CanEditIssue( |
| 1511 | {OWNER_ID}, permissions.COMMITTER_ACTIVE_PERMISSIONSET, |
| 1512 | self.PROJECT, self.REGULAR_ISSUE)) |
| 1513 | self.assertTrue(permissions.CanEditIssue( |
| 1514 | {OWNER_ID}, permissions.OWNER_ACTIVE_PERMISSIONSET, |
| 1515 | self.PROJECT, self.REGULAR_ISSUE)) |
| 1516 | self.assertTrue(permissions.CanEditIssue( |
| 1517 | {OTHER_ID}, permissions.COMMITTER_ACTIVE_PERMISSIONSET, |
| 1518 | self.PROJECT, self.REGULAR_ISSUE)) |
| 1519 | self.assertTrue(permissions.CanEditIssue( |
| 1520 | {OTHER_ID}, permissions.OWNER_ACTIVE_PERMISSIONSET, |
| 1521 | self.PROJECT, self.REGULAR_ISSUE)) |
| 1522 | |
| 1523 | def testCanEditIssue_Restricted(self): |
| 1524 | # Anon users cannot edit restricted issues. |
| 1525 | self.assertFalse(permissions.CanEditIssue( |
| 1526 | {}, permissions.COMMITTER_ACTIVE_PERMISSIONSET, |
| 1527 | self.PROJECT, self.RESTRICTED_ISSUE3)) |
| 1528 | |
| 1529 | # Project committers cannot edit issues with a restriction to a custom |
| 1530 | # permission that they don't have. |
| 1531 | self.assertFalse(permissions.CanEditIssue( |
| 1532 | {OTHER_ID}, permissions.COMMITTER_ACTIVE_PERMISSIONSET, |
| 1533 | self.PROJECT, self.RESTRICTED_ISSUE3)) |
| 1534 | |
| 1535 | # *Issue* owners can always edit the issues that they own, even if |
| 1536 | # those issues are restricted to perms that they don't have. |
| 1537 | self.assertTrue(permissions.CanEditIssue( |
| 1538 | {OWNER_ID}, permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET, |
| 1539 | self.PROJECT, self.RESTRICTED_ISSUE3)) |
| 1540 | |
| 1541 | # Project owners can always edit, they cannot lock themselves out. |
| 1542 | self.assertTrue(permissions.CanEditIssue( |
| 1543 | {OTHER_ID}, permissions.OWNER_ACTIVE_PERMISSIONSET, |
| 1544 | self.PROJECT, self.RESTRICTED_ISSUE3)) |
| 1545 | |
| 1546 | # A committer with edit permission but not view permission |
| 1547 | # should not be able to edit the issue. |
| 1548 | self.assertFalse(permissions.CanEditIssue( |
| 1549 | {OTHER_ID}, permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET, |
| 1550 | self.PROJECT, self.RESTRICTED_ISSUE2)) |
| 1551 | |
| 1552 | def testCanCommentIssue_HasPerm(self): |
| 1553 | self.assertTrue(permissions.CanCommentIssue( |
| 1554 | {111}, permissions.PermissionSet([permissions.ADD_ISSUE_COMMENT]), |
| 1555 | None, None)) |
| 1556 | self.assertFalse(permissions.CanCommentIssue( |
| 1557 | {111}, permissions.PermissionSet([]), |
| 1558 | None, None)) |
| 1559 | |
| 1560 | def testCanCommentIssue_HasExtraPerm(self): |
| 1561 | project = project_pb2.Project() |
| 1562 | project.committer_ids.append(111) |
| 1563 | extra_perm = project_pb2.Project.ExtraPerms( |
| 1564 | member_id=111, perms=[permissions.ADD_ISSUE_COMMENT]) |
| 1565 | project.extra_perms.append(extra_perm) |
| 1566 | self.assertTrue(permissions.CanCommentIssue( |
| 1567 | {111}, permissions.PermissionSet([]), |
| 1568 | project, None)) |
| 1569 | self.assertFalse(permissions.CanCommentIssue( |
| 1570 | {222}, permissions.PermissionSet([]), |
| 1571 | project, None)) |
| 1572 | |
| 1573 | def testCanCommentIssue_Restricted(self): |
| 1574 | issue = tracker_pb2.Issue(labels=['Restrict-AddIssueComment-CoreTeam']) |
| 1575 | # User is granted exactly the perm they need specifically in this issue. |
| 1576 | self.assertTrue(permissions.CanCommentIssue( |
| 1577 | {111}, permissions.PermissionSet([]), |
| 1578 | None, issue, granted_perms=['addissuecomment'])) |
| 1579 | # User is granted CoreTeam, which satifies the restriction, and allows |
| 1580 | # them to use the AddIssueComment permission that they have and would |
| 1581 | # normally be able to use in an unrestricted issue. |
| 1582 | self.assertTrue(permissions.CanCommentIssue( |
| 1583 | {111}, permissions.PermissionSet([permissions.ADD_ISSUE_COMMENT]), |
| 1584 | None, issue, granted_perms=['coreteam'])) |
| 1585 | # User was granted CoreTeam, but never had AddIssueComment. |
| 1586 | self.assertFalse(permissions.CanCommentIssue( |
| 1587 | {111}, permissions.PermissionSet([]), |
| 1588 | None, issue, granted_perms=['coreteam'])) |
| 1589 | # User has AddIssueComment, but cannot satisfy restriction. |
| 1590 | self.assertFalse(permissions.CanCommentIssue( |
| 1591 | {111}, permissions.PermissionSet([permissions.ADD_ISSUE_COMMENT]), |
| 1592 | None, issue)) |
| 1593 | |
| 1594 | def testCanCommentIssue_Granted(self): |
| 1595 | self.assertTrue(permissions.CanCommentIssue( |
| 1596 | {111}, permissions.PermissionSet([]), |
| 1597 | None, None, granted_perms=['addissuecomment'])) |
| 1598 | self.assertFalse(permissions.CanCommentIssue( |
| 1599 | {111}, permissions.PermissionSet([]), |
| 1600 | None, None)) |
| 1601 | |
| 1602 | def testCanUpdateApprovalStatus_Approver(self): |
| 1603 | # restricted status |
| 1604 | self.assertTrue(permissions.CanUpdateApprovalStatus( |
| 1605 | {111, 222}, permissions.PermissionSet([]), self.PROJECT, |
| 1606 | [222], tracker_pb2.ApprovalStatus.APPROVED)) |
| 1607 | |
| 1608 | # non-restricted status |
| 1609 | self.assertTrue(permissions.CanUpdateApprovalStatus( |
| 1610 | {111, 222}, permissions.PermissionSet([]), self.PROJECT, |
| 1611 | [222], tracker_pb2.ApprovalStatus.NEEDS_REVIEW)) |
| 1612 | |
| 1613 | def testCanUpdateApprovalStatus_SiteAdmin(self): |
| 1614 | # restricted status |
| 1615 | self.assertTrue(permissions.CanUpdateApprovalStatus( |
| 1616 | {444}, permissions.PermissionSet([permissions.EDIT_ISSUE_APPROVAL]), |
| 1617 | self.PROJECT, [222], tracker_pb2.ApprovalStatus.NOT_APPROVED)) |
| 1618 | |
| 1619 | # non-restricted status |
| 1620 | self.assertTrue(permissions.CanUpdateApprovalStatus( |
| 1621 | {444}, permissions.PermissionSet([permissions.EDIT_ISSUE_APPROVAL]), |
| 1622 | self.PROJECT, [222], tracker_pb2.ApprovalStatus.NEEDS_REVIEW)) |
| 1623 | |
| 1624 | def testCanUpdateApprovalStatus_NonApprover(self): |
| 1625 | # non-restricted status |
| 1626 | self.assertTrue(permissions.CanUpdateApprovalStatus( |
| 1627 | {111, 222}, permissions.PermissionSet([]), self.PROJECT, |
| 1628 | [333], tracker_pb2.ApprovalStatus.NEED_INFO)) |
| 1629 | |
| 1630 | # restricted status |
| 1631 | self.assertFalse(permissions.CanUpdateApprovalStatus( |
| 1632 | {111, 222}, permissions.PermissionSet([]), self.PROJECT, |
| 1633 | [333], tracker_pb2.ApprovalStatus.NA)) |
| 1634 | |
| 1635 | def testCanUpdateApprovers_Approver(self): |
| 1636 | self.assertTrue(permissions.CanUpdateApprovers( |
| 1637 | {111, 222}, permissions.PermissionSet([]), self.PROJECT, |
| 1638 | [222])) |
| 1639 | |
| 1640 | def testCanUpdateApprovers_SiteAdmins(self): |
| 1641 | self.assertTrue(permissions.CanUpdateApprovers( |
| 1642 | {444}, permissions.PermissionSet([permissions.EDIT_ISSUE_APPROVAL]), |
| 1643 | self.PROJECT, [222])) |
| 1644 | |
| 1645 | def testCanUpdateApprovers_NonApprover(self): |
| 1646 | self.assertFalse(permissions.CanUpdateApprovers( |
| 1647 | {111, 222}, permissions.PermissionSet([]), self.PROJECT, |
| 1648 | [333])) |
| 1649 | |
| 1650 | def testCanViewComponentDef_ComponentAdmin(self): |
| 1651 | cd = tracker_pb2.ComponentDef(admin_ids=[111]) |
| 1652 | perms = permissions.PermissionSet([]) |
| 1653 | self.assertTrue(permissions.CanViewComponentDef( |
| 1654 | {111}, perms, None, cd)) |
| 1655 | self.assertFalse(permissions.CanViewComponentDef( |
| 1656 | {999}, perms, None, cd)) |
| 1657 | |
| 1658 | def testCanViewComponentDef_NormalUser(self): |
| 1659 | cd = tracker_pb2.ComponentDef() |
| 1660 | self.assertTrue(permissions.CanViewComponentDef( |
| 1661 | {111}, permissions.PermissionSet([permissions.VIEW]), |
| 1662 | None, cd)) |
| 1663 | self.assertFalse(permissions.CanViewComponentDef( |
| 1664 | {111}, permissions.PermissionSet([]), |
| 1665 | None, cd)) |
| 1666 | |
| 1667 | def testCanEditComponentDef_ComponentAdmin(self): |
| 1668 | cd = tracker_pb2.ComponentDef(admin_ids=[111], path='Whole') |
| 1669 | sub_cd = tracker_pb2.ComponentDef(admin_ids=[222], path='Whole>Part') |
| 1670 | config = tracker_bizobj.MakeDefaultProjectIssueConfig(789) |
| 1671 | config.component_defs.append(cd) |
| 1672 | config.component_defs.append(sub_cd) |
| 1673 | perms = permissions.PermissionSet([]) |
| 1674 | self.assertTrue(permissions.CanEditComponentDef( |
| 1675 | {111}, perms, None, cd, config)) |
| 1676 | self.assertFalse(permissions.CanEditComponentDef( |
| 1677 | {222}, perms, None, cd, config)) |
| 1678 | self.assertFalse(permissions.CanEditComponentDef( |
| 1679 | {999}, perms, None, cd, config)) |
| 1680 | self.assertTrue(permissions.CanEditComponentDef( |
| 1681 | {111}, perms, None, sub_cd, config)) |
| 1682 | self.assertTrue(permissions.CanEditComponentDef( |
| 1683 | {222}, perms, None, sub_cd, config)) |
| 1684 | self.assertFalse(permissions.CanEditComponentDef( |
| 1685 | {999}, perms, None, sub_cd, config)) |
| 1686 | |
| 1687 | def testCanEditComponentDef_ProjectOwners(self): |
| 1688 | cd = tracker_pb2.ComponentDef(path='Whole') |
| 1689 | config = tracker_bizobj.MakeDefaultProjectIssueConfig(789) |
| 1690 | config.component_defs.append(cd) |
| 1691 | self.assertTrue(permissions.CanEditComponentDef( |
| 1692 | {111}, permissions.PermissionSet([permissions.EDIT_PROJECT]), |
| 1693 | None, cd, config)) |
| 1694 | self.assertFalse(permissions.CanEditComponentDef( |
| 1695 | {111}, permissions.PermissionSet([]), |
| 1696 | None, cd, config)) |
| 1697 | |
| 1698 | def testCanViewFieldDef_FieldAdmin(self): |
| 1699 | fd = tracker_pb2.FieldDef(admin_ids=[111]) |
| 1700 | perms = permissions.PermissionSet([]) |
| 1701 | self.assertTrue(permissions.CanViewFieldDef( |
| 1702 | {111}, perms, None, fd)) |
| 1703 | self.assertFalse(permissions.CanViewFieldDef( |
| 1704 | {999}, perms, None, fd)) |
| 1705 | |
| 1706 | def testCanViewFieldDef_NormalUser(self): |
| 1707 | fd = tracker_pb2.FieldDef() |
| 1708 | self.assertTrue(permissions.CanViewFieldDef( |
| 1709 | {111}, permissions.PermissionSet([permissions.VIEW]), |
| 1710 | None, fd)) |
| 1711 | self.assertFalse(permissions.CanViewFieldDef( |
| 1712 | {111}, permissions.PermissionSet([]), |
| 1713 | None, fd)) |
| 1714 | |
| 1715 | def testCanEditFieldDef_FieldAdmin(self): |
| 1716 | fd = tracker_pb2.FieldDef(admin_ids=[111]) |
| 1717 | perms = permissions.PermissionSet([]) |
| 1718 | self.assertTrue(permissions.CanEditFieldDef( |
| 1719 | {111}, perms, None, fd)) |
| 1720 | self.assertFalse(permissions.CanEditFieldDef( |
| 1721 | {999}, perms, None, fd)) |
| 1722 | |
| 1723 | def testCanEditFieldDef_ProjectOwners(self): |
| 1724 | fd = tracker_pb2.FieldDef() |
| 1725 | self.assertTrue(permissions.CanEditFieldDef( |
| 1726 | {111}, permissions.PermissionSet([permissions.EDIT_PROJECT]), |
| 1727 | None, fd)) |
| 1728 | self.assertFalse(permissions.CanEditFieldDef( |
| 1729 | {111}, permissions.PermissionSet([]), |
| 1730 | None, fd)) |
| 1731 | |
| 1732 | def testCanEditValueForFieldDef_NotRestrictedField(self): |
| 1733 | fd = tracker_pb2.FieldDef() |
| 1734 | perms = permissions.PermissionSet([]) |
| 1735 | self.assertTrue(permissions.CanEditValueForFieldDef({111}, perms, None, fd)) |
| 1736 | |
| 1737 | def testCanEditValueForFieldDef_RestrictedFieldEditor(self): |
| 1738 | fd = tracker_pb2.FieldDef(is_restricted_field=True, editor_ids=[111]) |
| 1739 | perms = permissions.PermissionSet([]) |
| 1740 | self.assertTrue(permissions.CanEditValueForFieldDef({111}, perms, None, fd)) |
| 1741 | self.assertFalse( |
| 1742 | permissions.CanEditValueForFieldDef({999}, perms, None, fd)) |
| 1743 | |
| 1744 | def testCanEditValueForFieldDef_RestrictedFieldAdmin(self): |
| 1745 | fd = tracker_pb2.FieldDef(is_restricted_field=True, admin_ids=[111]) |
| 1746 | perms = permissions.PermissionSet([]) |
| 1747 | self.assertTrue(permissions.CanEditValueForFieldDef({111}, perms, None, fd)) |
| 1748 | self.assertFalse( |
| 1749 | permissions.CanEditValueForFieldDef({999}, perms, None, fd)) |
| 1750 | |
| 1751 | def testCanEditValueForFieldDef_ProjectOwners(self): |
| 1752 | fd = tracker_pb2.FieldDef(is_restricted_field=True) |
| 1753 | self.assertTrue( |
| 1754 | permissions.CanEditValueForFieldDef( |
| 1755 | {111}, permissions.PermissionSet([permissions.EDIT_PROJECT]), None, |
| 1756 | fd)) |
| 1757 | self.assertFalse( |
| 1758 | permissions.CanEditValueForFieldDef( |
| 1759 | {111}, permissions.PermissionSet([]), None, fd)) |
| 1760 | |
| 1761 | def testCanViewTemplate_TemplateAdmin(self): |
| 1762 | td = tracker_pb2.TemplateDef(admin_ids=[111]) |
| 1763 | perms = permissions.PermissionSet([]) |
| 1764 | self.assertTrue(permissions.CanViewTemplate( |
| 1765 | {111}, perms, None, td)) |
| 1766 | self.assertFalse(permissions.CanViewTemplate( |
| 1767 | {999}, perms, None, td)) |
| 1768 | |
| 1769 | def testCanViewTemplate_MembersOnly(self): |
| 1770 | td = tracker_pb2.TemplateDef(members_only=True) |
| 1771 | project = project_pb2.Project(committer_ids=[111]) |
| 1772 | self.assertTrue(permissions.CanViewTemplate( |
| 1773 | {111}, permissions.PermissionSet([]), |
| 1774 | project, td)) |
| 1775 | self.assertFalse(permissions.CanViewTemplate( |
| 1776 | {999}, permissions.PermissionSet([]), |
| 1777 | project, td)) |
| 1778 | |
| 1779 | def testCanViewTemplate_AnyoneWhoCanViewProject(self): |
| 1780 | td = tracker_pb2.TemplateDef() |
| 1781 | self.assertTrue(permissions.CanViewTemplate( |
| 1782 | {111}, permissions.PermissionSet([permissions.VIEW]), |
| 1783 | None, td)) |
| 1784 | self.assertFalse(permissions.CanViewTemplate( |
| 1785 | {111}, permissions.PermissionSet([]), |
| 1786 | None, td)) |
| 1787 | |
| 1788 | def testCanEditTemplate_TemplateAdmin(self): |
| 1789 | td = tracker_pb2.TemplateDef(admin_ids=[111]) |
| 1790 | perms = permissions.PermissionSet([]) |
| 1791 | self.assertTrue(permissions.CanEditTemplate( |
| 1792 | {111}, perms, None, td)) |
| 1793 | self.assertFalse(permissions.CanEditTemplate( |
| 1794 | {999}, perms, None, td)) |
| 1795 | |
| 1796 | def testCanEditTemplate_ProjectOwners(self): |
| 1797 | td = tracker_pb2.TemplateDef() |
| 1798 | self.assertTrue(permissions.CanEditTemplate( |
| 1799 | {111}, permissions.PermissionSet([permissions.EDIT_PROJECT]), |
| 1800 | None, td)) |
| 1801 | self.assertFalse(permissions.CanEditTemplate( |
| 1802 | {111}, permissions.PermissionSet([]), |
| 1803 | None, td)) |
| 1804 | |
| 1805 | def testCanViewHotlist_Private(self): |
| 1806 | hotlist = features_pb2.Hotlist() |
| 1807 | hotlist.is_private = True |
| 1808 | hotlist.owner_ids.append(111) |
| 1809 | hotlist.editor_ids.append(222) |
| 1810 | |
| 1811 | self.assertTrue(permissions.CanViewHotlist({222}, self.PERMS, hotlist)) |
| 1812 | self.assertTrue(permissions.CanViewHotlist({111, 333}, self.PERMS, hotlist)) |
| 1813 | self.assertTrue( |
| 1814 | permissions.CanViewHotlist({111, 333}, self.ADMIN_PERMS, hotlist)) |
| 1815 | self.assertFalse( |
| 1816 | permissions.CanViewHotlist({333, 444}, self.PERMS, hotlist)) |
| 1817 | self.assertTrue( |
| 1818 | permissions.CanViewHotlist({333, 444}, self.ADMIN_PERMS, hotlist)) |
| 1819 | |
| 1820 | def testCanViewHotlist_Public(self): |
| 1821 | hotlist = features_pb2.Hotlist() |
| 1822 | hotlist.is_private = False |
| 1823 | hotlist.owner_ids.append(111) |
| 1824 | hotlist.editor_ids.append(222) |
| 1825 | |
| 1826 | self.assertTrue(permissions.CanViewHotlist({222}, self.PERMS, hotlist)) |
| 1827 | self.assertTrue(permissions.CanViewHotlist({111, 333}, self.PERMS, hotlist)) |
| 1828 | self.assertTrue(permissions.CanViewHotlist({333, 444}, self.PERMS, hotlist)) |
| 1829 | self.assertTrue( |
| 1830 | permissions.CanViewHotlist({333, 444}, self.ADMIN_PERMS, hotlist)) |
| 1831 | |
| 1832 | def testCanEditHotlist(self): |
| 1833 | hotlist = features_pb2.Hotlist() |
| 1834 | hotlist.owner_ids.append(111) |
| 1835 | hotlist.editor_ids.append(222) |
| 1836 | |
| 1837 | self.assertTrue(permissions.CanEditHotlist({222}, self.PERMS, hotlist)) |
| 1838 | self.assertTrue(permissions.CanEditHotlist({111, 333}, self.PERMS, hotlist)) |
| 1839 | self.assertTrue( |
| 1840 | permissions.CanEditHotlist({111, 333}, self.ADMIN_PERMS, hotlist)) |
| 1841 | self.assertFalse( |
| 1842 | permissions.CanEditHotlist({333, 444}, self.PERMS, hotlist)) |
| 1843 | self.assertTrue( |
| 1844 | permissions.CanEditHotlist({333, 444}, self.ADMIN_PERMS, hotlist)) |
| 1845 | |
| 1846 | def testCanAdministerHotlist(self): |
| 1847 | hotlist = features_pb2.Hotlist() |
| 1848 | hotlist.owner_ids.append(111) |
| 1849 | hotlist.editor_ids.append(222) |
| 1850 | |
| 1851 | self.assertFalse( |
| 1852 | permissions.CanAdministerHotlist({222}, self.PERMS, hotlist)) |
| 1853 | self.assertTrue( |
| 1854 | permissions.CanAdministerHotlist({111, 333}, self.PERMS, hotlist)) |
| 1855 | self.assertTrue( |
| 1856 | permissions.CanAdministerHotlist({111, 333}, self.ADMIN_PERMS, hotlist)) |
| 1857 | self.assertFalse( |
| 1858 | permissions.CanAdministerHotlist({333, 444}, self.PERMS, hotlist)) |
| 1859 | self.assertTrue( |
| 1860 | permissions.CanAdministerHotlist({333, 444}, self.ADMIN_PERMS, hotlist)) |