diff options
Diffstat (limited to 'gerrit-server/src/main/java/com/google/gerrit/server/project/SetAccess.java')
-rw-r--r-- | gerrit-server/src/main/java/com/google/gerrit/server/project/SetAccess.java | 219 |
1 files changed, 33 insertions, 186 deletions
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/SetAccess.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/SetAccess.java index c74efc6473..e875388817 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/project/SetAccess.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/SetAccess.java @@ -14,18 +14,10 @@ package com.google.gerrit.server.project; -import com.google.common.base.MoreObjects; import com.google.common.base.Strings; +import com.google.common.collect.Iterables; import com.google.gerrit.common.data.AccessSection; -import com.google.gerrit.common.data.GlobalCapability; -import com.google.gerrit.common.data.GroupDescription; -import com.google.gerrit.common.data.GroupReference; -import com.google.gerrit.common.data.Permission; -import com.google.gerrit.common.data.PermissionRule; import com.google.gerrit.common.errors.InvalidNameException; -import com.google.gerrit.extensions.api.access.AccessSectionInfo; -import com.google.gerrit.extensions.api.access.PermissionInfo; -import com.google.gerrit.extensions.api.access.PermissionRuleInfo; import com.google.gerrit.extensions.api.access.ProjectAccessInfo; import com.google.gerrit.extensions.api.access.ProjectAccessInput; import com.google.gerrit.extensions.restapi.AuthException; @@ -37,161 +29,85 @@ import com.google.gerrit.extensions.restapi.UnprocessableEntityException; import com.google.gerrit.reviewdb.client.Project; import com.google.gerrit.server.IdentifiedUser; import com.google.gerrit.server.account.GroupBackend; -import com.google.gerrit.server.config.AllProjectsName; import com.google.gerrit.server.git.MetaDataUpdate; import com.google.gerrit.server.git.ProjectConfig; -import com.google.gerrit.server.group.GroupsCollection; +import com.google.gerrit.server.permissions.GlobalPermission; +import com.google.gerrit.server.permissions.PermissionBackend; +import com.google.gerrit.server.permissions.PermissionBackendException; +import com.google.gwtorm.server.OrmException; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.Singleton; import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; import java.util.List; -import java.util.Map; import org.eclipse.jgit.errors.ConfigInvalidException; @Singleton public class SetAccess implements RestModifyView<ProjectResource, ProjectAccessInput> { protected final GroupBackend groupBackend; - private final GroupsCollection groupsCollection; + private final PermissionBackend permissionBackend; private final Provider<MetaDataUpdate.User> metaDataUpdateFactory; - private final AllProjectsName allProjects; - private final Provider<SetParent> setParent; private final GetAccess getAccess; private final ProjectCache projectCache; private final Provider<IdentifiedUser> identifiedUser; + private final SetAccessUtil accessUtil; @Inject private SetAccess( GroupBackend groupBackend, + PermissionBackend permissionBackend, Provider<MetaDataUpdate.User> metaDataUpdateFactory, - AllProjectsName allProjects, - Provider<SetParent> setParent, - GroupsCollection groupsCollection, ProjectCache projectCache, GetAccess getAccess, - Provider<IdentifiedUser> identifiedUser) { + Provider<IdentifiedUser> identifiedUser, + SetAccessUtil accessUtil) { this.groupBackend = groupBackend; + this.permissionBackend = permissionBackend; this.metaDataUpdateFactory = metaDataUpdateFactory; - this.allProjects = allProjects; - this.setParent = setParent; - this.groupsCollection = groupsCollection; this.getAccess = getAccess; this.projectCache = projectCache; this.identifiedUser = identifiedUser; + this.accessUtil = accessUtil; } @Override public ProjectAccessInfo apply(ProjectResource rsrc, ProjectAccessInput input) throws ResourceNotFoundException, ResourceConflictException, IOException, AuthException, - BadRequestException, UnprocessableEntityException { - List<AccessSection> removals = getAccessSections(input.remove); - List<AccessSection> additions = getAccessSections(input.add); + BadRequestException, UnprocessableEntityException, OrmException, + PermissionBackendException { MetaDataUpdate.User metaDataUpdateUser = metaDataUpdateFactory.get(); - ProjectControl projectControl = rsrc.getControl(); ProjectConfig config; - Project.NameKey newParentProjectName = - input.parent == null ? null : new Project.NameKey(input.parent); - + List<AccessSection> removals = accessUtil.getAccessSections(input.remove); + List<AccessSection> additions = accessUtil.getAccessSections(input.add); try (MetaDataUpdate md = metaDataUpdateUser.create(rsrc.getNameKey())) { config = ProjectConfig.read(md); - // Perform removal checks - for (AccessSection section : removals) { + // Check that the user has the right permissions. + boolean checkedAdmin = false; + for (AccessSection section : Iterables.concat(additions, removals)) { boolean isGlobalCapabilities = AccessSection.GLOBAL_CAPABILITIES.equals(section.getName()); - - if (isGlobalCapabilities) { - checkGlobalCapabilityPermissions(config.getName()); - } else if (!projectControl.controlForRef(section.getName()).isOwner()) { - throw new AuthException( - "You are not allowed to edit permissionsfor ref: " + section.getName()); - } - } - // Perform addition checks - for (AccessSection section : additions) { - String name = section.getName(); - boolean isGlobalCapabilities = AccessSection.GLOBAL_CAPABILITIES.equals(name); - if (isGlobalCapabilities) { - checkGlobalCapabilityPermissions(config.getName()); - } else { - if (!AccessSection.isValid(name)) { - throw new BadRequestException("invalid section name"); - } - if (!projectControl.controlForRef(name).isOwner()) { - throw new AuthException("You are not allowed to edit permissionsfor ref: " + name); - } - RefPattern.validate(name); - } - - // Check all permissions for soundness - for (Permission p : section.getPermissions()) { - if (isGlobalCapabilities && !GlobalCapability.isCapability(p.getName())) { - throw new BadRequestException( - "Cannot add non-global capability " + p.getName() + " to global capabilities"); - } - } - } - - // Apply removals - for (AccessSection section : removals) { - if (section.getPermissions().isEmpty()) { - // Remove entire section - config.remove(config.getAccessSection(section.getName())); - } - // Remove specific permissions - for (Permission p : section.getPermissions()) { - if (p.getRules().isEmpty()) { - config.remove(config.getAccessSection(section.getName()), p); - } else { - for (PermissionRule r : p.getRules()) { - config.remove(config.getAccessSection(section.getName()), p, r); - } + if (!checkedAdmin) { + permissionBackend.user(identifiedUser).check(GlobalPermission.ADMINISTRATE_SERVER); + checkedAdmin = true; } + } else if (!rsrc.getControl().controlForRef(section.getName()).isOwner()) { + throw new AuthException( + "You are not allowed to edit permissions for ref: " + section.getName()); } } - // Apply additions - for (AccessSection section : additions) { - AccessSection currentAccessSection = config.getAccessSection(section.getName()); + accessUtil.validateChanges(config, removals, additions); + accessUtil.applyChanges(config, removals, additions); - if (currentAccessSection == null) { - // Add AccessSection - config.replace(section); - } else { - for (Permission p : section.getPermissions()) { - Permission currentPermission = currentAccessSection.getPermission(p.getName()); - if (currentPermission == null) { - // Add Permission - currentAccessSection.addPermission(p); - } else { - for (PermissionRule r : p.getRules()) { - // AddPermissionRule - currentPermission.add(r); - } - } - } - } - } - - if (newParentProjectName != null - && !config.getProject().getNameKey().equals(allProjects) - && !config.getProject().getParent(allProjects).equals(newParentProjectName)) { - try { - setParent - .get() - .validateParentUpdate( - projectControl, - MoreObjects.firstNonNull(newParentProjectName, allProjects).get(), - true); - } catch (UnprocessableEntityException e) { - throw new ResourceConflictException(e.getMessage(), e); - } - config.getProject().setParentName(newParentProjectName); - } + accessUtil.setParentName( + identifiedUser.get(), + config, + rsrc.getNameKey(), + input.parent == null ? null : new Project.NameKey(input.parent), + !checkedAdmin); if (!Strings.isNullOrEmpty(input.message)) { if (!input.message.endsWith("\n")) { @@ -212,73 +128,4 @@ public class SetAccess implements RestModifyView<ProjectResource, ProjectAccessI return getAccess.apply(rsrc.getNameKey()); } - - private List<AccessSection> getAccessSections(Map<String, AccessSectionInfo> sectionInfos) - throws UnprocessableEntityException { - if (sectionInfos == null) { - return Collections.emptyList(); - } - - List<AccessSection> sections = new ArrayList<>(sectionInfos.size()); - for (Map.Entry<String, AccessSectionInfo> entry : sectionInfos.entrySet()) { - AccessSection accessSection = new AccessSection(entry.getKey()); - - if (entry.getValue().permissions == null) { - continue; - } - - for (Map.Entry<String, PermissionInfo> permissionEntry : - entry.getValue().permissions.entrySet()) { - Permission p = new Permission(permissionEntry.getKey()); - if (permissionEntry.getValue().exclusive != null) { - p.setExclusiveGroup(permissionEntry.getValue().exclusive); - } - - if (permissionEntry.getValue().rules == null) { - continue; - } - for (Map.Entry<String, PermissionRuleInfo> permissionRuleInfoEntry : - permissionEntry.getValue().rules.entrySet()) { - PermissionRuleInfo pri = permissionRuleInfoEntry.getValue(); - - GroupDescription.Basic group = groupsCollection.parseId(permissionRuleInfoEntry.getKey()); - if (group == null) { - throw new UnprocessableEntityException( - permissionRuleInfoEntry.getKey() + " is not a valid group ID"); - } - PermissionRule r = new PermissionRule(GroupReference.forGroup(group)); - if (pri != null) { - if (pri.max != null) { - r.setMax(pri.max); - } - if (pri.min != null) { - r.setMin(pri.min); - } - r.setAction(GetAccess.ACTION_TYPE.inverse().get(pri.action)); - if (pri.force != null) { - r.setForce(pri.force); - } - } - p.add(r); - } - accessSection.getPermissions().add(p); - } - sections.add(accessSection); - } - return sections; - } - - private void checkGlobalCapabilityPermissions(Project.NameKey projectName) - throws BadRequestException, AuthException { - - if (!allProjects.equals(projectName)) { - throw new BadRequestException( - "Cannot edit global capabilities for projects other than " + allProjects.get()); - } - - if (!identifiedUser.get().getCapabilities().canAdministrateServer()) { - throw new AuthException( - "Editing global capabilities requires " + GlobalCapability.ADMINISTRATE_SERVER); - } - } } |