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