Merge branch 'main' into avm99963-monorail

Merged commit 34d8229ae2b51fb1a15bd208e6fe6185c94f6266

GitOrigin-RevId: 7ee0917f93a577e475f8e09526dd144d245593f4
diff --git a/framework/test/permissions_test.py b/framework/test/permissions_test.py
index cd67c6c..6280208 100644
--- a/framework/test/permissions_test.py
+++ b/framework/test/permissions_test.py
@@ -1,13 +1,13 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file or at
-# https://developers.google.com/open-source/licenses/bsd
+# Copyright 2016 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
 
 """Tests for permissions.py."""
 from __future__ import print_function
 from __future__ import division
 from __future__ import absolute_import
 
+import six
 import time
 import unittest
 
@@ -21,12 +21,13 @@
 from framework import framework_constants
 from framework import framework_views
 from framework import permissions
-from proto import features_pb2
-from proto import project_pb2
-from proto import site_pb2
-from proto import tracker_pb2
-from proto import user_pb2
-from proto import usergroup_pb2
+from mrproto import features_pb2
+from mrproto import project_pb2
+from mrproto import site_pb2
+from mrproto import tracker_pb2
+from mrproto import user_pb2
+from mrproto import usergroup_pb2
+from services import service_manager
 from testing import fake
 from testing import testing_helpers
 from tracker import tracker_bizobj
@@ -160,10 +161,20 @@
     self.assertEqual('PermissionSet(a, b, cc)', self.perms.DebugString())
 
   def testRepr(self):
-    self.assertEqual('PermissionSet(frozenset([]))',
-                     permissions.PermissionSet([]).__repr__())
-    self.assertEqual('PermissionSet(frozenset([\'a\']))',
-                     permissions.PermissionSet(['A']).__repr__())
+    if six.PY2:
+      self.assertEqual(
+          'PermissionSet(frozenset([]))',
+          permissions.PermissionSet([]).__repr__())
+      self.assertEqual(
+          "PermissionSet(frozenset(['a']))",
+          permissions.PermissionSet(['A']).__repr__())
+    else:
+      self.assertEqual(
+          'PermissionSet(frozenset())',
+          permissions.PermissionSet([]).__repr__())
+      self.assertEqual(
+          "PermissionSet(frozenset({'a'}))",
+          permissions.PermissionSet(['A']).__repr__())
 
 
 class PermissionsTest(unittest.TestCase):
@@ -953,8 +964,9 @@
         None, None, self.live_project))
 
     self.archived_project.delete_time = self.NOW + 1
-    self.assertFalse(permissions.UserCanViewProject(
-        None, None, self.archived_project))
+    # Anonymous users may view an archived project.
+    self.assertTrue(
+        permissions.UserCanViewProject(None, None, self.archived_project))
     self.assertTrue(permissions.UserCanViewProject(
         self.owner, {self.OWNER_USER_ID}, self.archived_project))
     self.assertTrue(permissions.UserCanViewProject(
@@ -1230,6 +1242,14 @@
   ADMIN_PERMS = permissions.ADMIN_PERMISSIONSET
   PERMS = permissions.EMPTY_PERMISSIONSET
 
+  def setUp(self):
+    self.user_svc = fake.UserService()
+    self.services = service_manager.Services(user=self.user_svc)
+
+    self.user_svc.TestAddUser('allowlisteduser@test.com', 567)
+
+    settings.config_freeze_project_ids = {}
+
   def testUpdateIssuePermissions_Normal(self):
     perms = permissions.UpdateIssuePermissions(
         permissions.COMMITTER_ACTIVE_PERMISSIONSET, self.PROJECT,
@@ -1366,6 +1386,21 @@
         self.RESTRICTED_ISSUE3, {OWNER_ID})
     self.assertIn('editissue', perms.perm_names)
 
+  def testUpdateIssuePermissions_DefaultPermsDoNotIncludeEdit(self):
+    # Permissions can be checked from the homepage without a project context.
+    perms = permissions.UpdateIssuePermissions(
+        permissions.COMMITTER_ACTIVE_PERMISSIONSET, None,
+        self.RESTRICTED_ISSUE3, {OWNER_ID})
+    self.assertNotIn('editissue', perms.perm_names)
+
+  def testUpdateIssuePermissions_OwnerRespectsArchivedProject(self):
+    project = project_pb2.Project()
+    project.state = project_pb2.ProjectState.ARCHIVED
+    perms = permissions.UpdateIssuePermissions(
+        permissions.COMMITTER_ACTIVE_PERMISSIONSET, project,
+        self.RESTRICTED_ISSUE3, {OWNER_ID})
+    self.assertNotIn('editissue', perms.perm_names)
+
   def testUpdateIssuePermissions_CustomPermissionGrantsEditPermission(self):
     project = project_pb2.Project()
     project.committer_ids.append(999)
@@ -1650,6 +1685,39 @@
         {111, 222}, permissions.PermissionSet([]), self.PROJECT,
         [333]))
 
+  def testCanEditProjectConfig_Admin(self):
+    mr = testing_helpers.MakeMonorailRequest(
+        project=fake.Project(project_id=789))
+    mr.perms = permissions.ADMIN_PERMISSIONSET
+    self.assertTrue(permissions.CanEditProjectConfig(mr, self.services))
+
+  def testCanEditProjectConfig_NormalUser(self):
+    mr = testing_helpers.MakeMonorailRequest(
+        project=fake.Project(project_id=789))
+    mr.perms = permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET
+    self.assertFalse(permissions.CanEditProjectConfig(mr, self.services))
+
+  def testCanEditProjectConfig_Admin_FrozenConfig(self):
+    mr = testing_helpers.MakeMonorailRequest(
+        project=fake.Project(project_id=789))
+    mr.perms = permissions.ADMIN_PERMISSIONSET
+    mr.auth.effective_ids = {567}
+
+    settings.config_freeze_override_users = {}
+    settings.config_freeze_project_ids = {789}
+    self.assertFalse(permissions.CanEditProjectConfig(mr, self.services))
+
+  def testCanEditProjectConfig_Admin_FrozenConfig_AllowedUser(self):
+    mr = testing_helpers.MakeMonorailRequest(
+        project=fake.Project(project_id=789))
+    mr.perms = permissions.ADMIN_PERMISSIONSET
+    mr.auth.effective_ids = {567}
+
+    settings.config_freeze_override_users = {789: 'allowlisteduser@test.com'}
+    settings.config_freeze_project_ids = {789}
+
+    self.assertTrue(permissions.CanEditProjectConfig(mr, self.services))
+
   def testCanViewComponentDef_ComponentAdmin(self):
     cd = tracker_pb2.ComponentDef(admin_ids=[111])
     perms = permissions.PermissionSet([])
@@ -1667,36 +1735,51 @@
         {111}, permissions.PermissionSet([]),
         None, cd))
 
-  def testCanEditComponentDef_ComponentAdmin(self):
+  def testCanEditComponentDefLegacy_ComponentAdmin(self):
     cd = tracker_pb2.ComponentDef(admin_ids=[111], path='Whole')
     sub_cd = tracker_pb2.ComponentDef(admin_ids=[222], path='Whole>Part')
     config = tracker_bizobj.MakeDefaultProjectIssueConfig(789)
     config.component_defs.append(cd)
     config.component_defs.append(sub_cd)
     perms = permissions.PermissionSet([])
-    self.assertTrue(permissions.CanEditComponentDef(
-        {111}, perms, None, cd, config))
-    self.assertFalse(permissions.CanEditComponentDef(
-        {222}, perms, None, cd, config))
-    self.assertFalse(permissions.CanEditComponentDef(
-        {999}, perms, None, cd, config))
-    self.assertTrue(permissions.CanEditComponentDef(
-        {111}, perms, None, sub_cd, config))
-    self.assertTrue(permissions.CanEditComponentDef(
-        {222}, perms, None, sub_cd, config))
-    self.assertFalse(permissions.CanEditComponentDef(
-        {999}, perms, None, sub_cd, config))
+    self.assertTrue(
+        permissions.CanEditComponentDefLegacy({111}, perms, None, cd, config))
+    self.assertFalse(
+        permissions.CanEditComponentDefLegacy({222}, perms, None, cd, config))
+    self.assertFalse(
+        permissions.CanEditComponentDefLegacy({999}, perms, None, cd, config))
+    self.assertTrue(
+        permissions.CanEditComponentDefLegacy(
+            {111}, perms, None, sub_cd, config))
+    self.assertTrue(
+        permissions.CanEditComponentDefLegacy(
+            {222}, perms, None, sub_cd, config))
+    self.assertFalse(
+        permissions.CanEditComponentDefLegacy(
+            {999}, perms, None, sub_cd, config))
 
-  def testCanEditComponentDef_ProjectOwners(self):
+  def testCanEditComponentDefLegacy_ProjectOwners(self):
     cd = tracker_pb2.ComponentDef(path='Whole')
     config = tracker_bizobj.MakeDefaultProjectIssueConfig(789)
     config.component_defs.append(cd)
-    self.assertTrue(permissions.CanEditComponentDef(
-        {111}, permissions.PermissionSet([permissions.EDIT_PROJECT]),
-        None, cd, config))
-    self.assertFalse(permissions.CanEditComponentDef(
-        {111}, permissions.PermissionSet([]),
-        None, cd, config))
+    self.assertTrue(
+        permissions.CanEditComponentDefLegacy(
+            {111}, permissions.PermissionSet([permissions.EDIT_PROJECT]), None,
+            cd, config))
+    self.assertFalse(
+        permissions.CanEditComponentDefLegacy(
+            {111}, permissions.PermissionSet([]), None, cd, config))
+
+  def testCanEditComponentDefLegacy_FrozenProject(self):
+    cd = tracker_pb2.ComponentDef(path='Whole')
+    config = tracker_bizobj.MakeDefaultProjectIssueConfig(789)
+    config.component_defs.append(cd)
+    project = project_pb2.Project(project_id=789)
+    settings.config_freeze_project_ids = {789}
+    self.assertFalse(
+        permissions.CanEditComponentDefLegacy(
+            {111}, permissions.PermissionSet([permissions.EDIT_PROJECT]),
+            project, cd, config))
 
   def testCanViewFieldDef_FieldAdmin(self):
     fd = tracker_pb2.FieldDef(admin_ids=[111])