Line data Source code
1 : // Copyright (C) 2020 The Android Open Source Project 2 : // 3 : // Licensed under the Apache License, Version 2.0 (the "License"); 4 : // you may not use this file except in compliance with the License. 5 : // You may obtain a copy of the License at 6 : // 7 : // http://www.apache.org/licenses/LICENSE-2.0 8 : // 9 : // Unless required by applicable law or agreed to in writing, software 10 : // distributed under the License is distributed on an "AS IS" BASIS, 11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 : // See the License for the specific language governing permissions and 13 : // limitations under the License. 14 : 15 : package com.google.gerrit.server.schema; 16 : 17 : import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS; 18 : import static com.google.gerrit.server.schema.AclUtil.grant; 19 : import static com.google.gerrit.server.schema.AclUtil.remove; 20 : 21 : import com.google.gerrit.entities.AccessSection; 22 : import com.google.gerrit.entities.GroupReference; 23 : import com.google.gerrit.entities.Permission; 24 : import com.google.gerrit.entities.Project; 25 : import com.google.gerrit.server.GerritPersonIdent; 26 : import com.google.gerrit.server.extensions.events.GitReferenceUpdated; 27 : import com.google.gerrit.server.git.GitRepositoryManager; 28 : import com.google.gerrit.server.git.meta.MetaDataUpdate; 29 : import com.google.gerrit.server.group.SystemGroupBackend; 30 : import com.google.gerrit.server.project.ProjectConfig; 31 : import com.google.inject.Inject; 32 : import java.io.IOException; 33 : import java.util.concurrent.atomic.AtomicBoolean; 34 : import org.eclipse.jgit.errors.ConfigInvalidException; 35 : import org.eclipse.jgit.lib.PersonIdent; 36 : import org.eclipse.jgit.lib.Repository; 37 : 38 : /** 39 : * This class adds the "revert" permission to all hosts that call this method with the relevant 40 : * projectName. This class should be called with AllProjects as the project, by all hosts before 41 : * enabling the "revert" permission. 42 : */ 43 : public class GrantRevertPermission { 44 : 45 : private final GitRepositoryManager repoManager; 46 : private final ProjectConfig.Factory projectConfigFactory; 47 : private final SystemGroupBackend systemGroupBackend; 48 : private final PersonIdent serverUser; 49 : 50 : @Inject 51 : public GrantRevertPermission( 52 : GitRepositoryManager repoManager, 53 : ProjectConfig.Factory projectConfigFactory, 54 : SystemGroupBackend systemGroupBackend, 55 1 : @GerritPersonIdent PersonIdent serverUser) { 56 1 : this.repoManager = repoManager; 57 1 : this.projectConfigFactory = projectConfigFactory; 58 1 : this.systemGroupBackend = systemGroupBackend; 59 1 : this.serverUser = serverUser; 60 1 : } 61 : 62 : public void execute(Project.NameKey projectName) throws IOException, ConfigInvalidException { 63 1 : GroupReference registeredUsers = systemGroupBackend.getGroup(REGISTERED_USERS); 64 1 : try (Repository repo = repoManager.openRepository(projectName)) { 65 1 : MetaDataUpdate md = new MetaDataUpdate(GitReferenceUpdated.DISABLED, projectName, repo); 66 1 : ProjectConfig projectConfig = projectConfigFactory.read(md); 67 : 68 1 : AtomicBoolean shouldExit = new AtomicBoolean(false); 69 1 : projectConfig.upsertAccessSection( 70 : AccessSection.HEADS, 71 : heads -> { 72 1 : Permission permissionOnRefsHeads = heads.build().getPermission(Permission.REVERT); 73 : 74 1 : if (permissionOnRefsHeads != null) { 75 1 : if (permissionOnRefsHeads.getRule(registeredUsers) == null 76 1 : || permissionOnRefsHeads.getRules().size() > 1) { 77 : // If admins already changed the permission, don't do anything. 78 1 : shouldExit.set(true); 79 1 : return; 80 : } 81 : // permission already exists in refs/heads/*, delete it for Registered Users. 82 1 : remove(projectConfig, heads, Permission.REVERT, registeredUsers); 83 : } 84 1 : }); 85 : 86 1 : if (shouldExit.get()) { 87 1 : return; 88 : } 89 : 90 1 : projectConfig.upsertAccessSection( 91 : AccessSection.ALL, 92 : all -> { 93 1 : Permission permissionOnRefsStar = all.build().getPermission(Permission.REVERT); 94 1 : if (permissionOnRefsStar != null 95 1 : && permissionOnRefsStar.getRule(registeredUsers) != null) { 96 : // permission already exists in refs/*, don't do anything. 97 1 : return; 98 : } 99 : // If the permission doesn't exist of refs/* for Registered Users, grant it. 100 1 : grant(projectConfig, all, Permission.REVERT, registeredUsers); 101 1 : }); 102 : 103 1 : md.getCommitBuilder().setAuthor(serverUser); 104 1 : md.getCommitBuilder().setCommitter(serverUser); 105 1 : md.setMessage("Add revert permission for all registered users\n"); 106 : 107 1 : projectConfig.commit(md); 108 1 : } 109 1 : } 110 : }