Search in sources :

Example 11 with AccessSection

use of com.google.gerrit.entities.AccessSection in project gerrit by GerritCodeReview.

the class SetAccessUtil method getAccessSections.

ImmutableList<AccessSection> getAccessSections(Map<String, AccessSectionInfo> sectionInfos) throws UnprocessableEntityException {
    if (sectionInfos == null) {
        return ImmutableList.of();
    }
    ImmutableList.Builder<AccessSection> sections = ImmutableList.builderWithExpectedSize(sectionInfos.size());
    for (Map.Entry<String, AccessSectionInfo> entry : sectionInfos.entrySet()) {
        if (entry.getValue().permissions == null) {
            continue;
        }
        AccessSection.Builder accessSection = AccessSection.builder(entry.getKey());
        for (Map.Entry<String, PermissionInfo> permissionEntry : entry.getValue().permissions.entrySet()) {
            if (permissionEntry.getValue().rules == null) {
                continue;
            }
            Permission.Builder p = Permission.builder(permissionEntry.getKey());
            if (permissionEntry.getValue().exclusive != null) {
                p.setExclusiveGroup(permissionEntry.getValue().exclusive);
            }
            for (Map.Entry<String, PermissionRuleInfo> permissionRuleInfoEntry : permissionEntry.getValue().rules.entrySet()) {
                GroupDescription.Basic group = groupResolver.parseId(permissionRuleInfoEntry.getKey());
                if (group == null) {
                    throw new UnprocessableEntityException(permissionRuleInfoEntry.getKey() + " is not a valid group ID");
                }
                PermissionRuleInfo pri = permissionRuleInfoEntry.getValue();
                PermissionRule.Builder r = PermissionRule.builder(GroupReference.forGroup(group));
                if (pri != null) {
                    if (pri.max != null) {
                        r.setMax(pri.max);
                    }
                    if (pri.min != null) {
                        r.setMin(pri.min);
                    }
                    if (pri.action != null) {
                        r.setAction(GetAccess.ACTION_TYPE.inverse().get(pri.action));
                    }
                    if (pri.force != null) {
                        r.setForce(pri.force);
                    }
                }
                p.add(r);
            }
            accessSection.addPermission(p);
        }
        sections.add(accessSection.build());
    }
    return sections.build();
}
Also used : UnprocessableEntityException(com.google.gerrit.extensions.restapi.UnprocessableEntityException) PermissionRule(com.google.gerrit.entities.PermissionRule) ImmutableList(com.google.common.collect.ImmutableList) AccessSection(com.google.gerrit.entities.AccessSection) GroupDescription(com.google.gerrit.entities.GroupDescription) PermissionInfo(com.google.gerrit.extensions.api.access.PermissionInfo) Permission(com.google.gerrit.entities.Permission) PermissionRuleInfo(com.google.gerrit.extensions.api.access.PermissionRuleInfo) AccessSectionInfo(com.google.gerrit.extensions.api.access.AccessSectionInfo) Map(java.util.Map)

Example 12 with AccessSection

use of com.google.gerrit.entities.AccessSection in project gerrit by GerritCodeReview.

the class SetAccessUtil method validateChanges.

/**
 * Checks that the removals and additions are logically valid, but doesn't check current user's
 * permission.
 */
void validateChanges(ProjectConfig config, List<AccessSection> removals, List<AccessSection> additions) throws BadRequestException, InvalidNameException {
    // Perform permission checks
    for (AccessSection section : Iterables.concat(additions, removals)) {
        boolean isGlobalCapabilities = AccessSection.GLOBAL_CAPABILITIES.equals(section.getName());
        if (isGlobalCapabilities) {
            if (!allProjects.equals(config.getName())) {
                throw new BadRequestException("Cannot edit global capabilities for projects other than " + allProjects.get());
            }
        }
    }
    // Perform addition checks
    for (AccessSection section : additions) {
        String name = section.getName();
        boolean isGlobalCapabilities = AccessSection.GLOBAL_CAPABILITIES.equals(name);
        if (!isGlobalCapabilities) {
            if (!AccessSection.isValidRefSectionName(name)) {
                throw new BadRequestException("invalid section name");
            }
            RefPattern.validate(name);
            // Check all permissions for soundness
            for (Permission p : section.getPermissions()) {
                if (!isPermission(p.getName())) {
                    throw new BadRequestException("Unknown permission: " + p.getName());
                }
            }
        } else {
            // Check all permissions for soundness
            for (Permission p : section.getPermissions()) {
                if (!isCapability(p.getName())) {
                    throw new BadRequestException("Unknown global capability: " + p.getName());
                }
            }
        }
    }
}
Also used : Permission(com.google.gerrit.entities.Permission) BadRequestException(com.google.gerrit.extensions.restapi.BadRequestException) AccessSection(com.google.gerrit.entities.AccessSection)

Example 13 with AccessSection

use of com.google.gerrit.entities.AccessSection in project gerrit by GerritCodeReview.

the class SetAccess method apply.

@Override
public Response<ProjectAccessInfo> apply(ProjectResource rsrc, ProjectAccessInput input) throws Exception {
    MetaDataUpdate.User metaDataUpdateUser = metaDataUpdateFactory.get();
    ProjectConfig config;
    List<AccessSection> removals = accessUtil.getAccessSections(input.remove);
    List<AccessSection> additions = accessUtil.getAccessSections(input.add);
    try (MetaDataUpdate md = metaDataUpdateUser.create(rsrc.getNameKey())) {
        config = projectConfigFactory.read(md);
        // 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) {
                if (!checkedAdmin) {
                    permissionBackend.currentUser().check(GlobalPermission.ADMINISTRATE_SERVER);
                    checkedAdmin = true;
                }
            } else {
                permissionBackend.currentUser().project(rsrc.getNameKey()).ref(section.getName()).check(RefPermission.WRITE_CONFIG);
            }
        }
        accessUtil.validateChanges(config, removals, additions);
        accessUtil.applyChanges(config, removals, additions);
        accessUtil.setParentName(identifiedUser.get(), config, rsrc.getNameKey(), input.parent == null ? null : Project.nameKey(input.parent), !checkedAdmin);
        if (!Strings.isNullOrEmpty(input.message)) {
            if (!input.message.endsWith("\n")) {
                input.message += "\n";
            }
            md.setMessage(input.message);
        } else {
            md.setMessage("Modify access rules\n");
        }
        config.commit(md);
        projectCache.evictAndReindex(config.getProject());
        createGroupPermissionSyncer.syncIfNeeded();
    } catch (InvalidNameException e) {
        throw new BadRequestException(e.toString());
    } catch (ConfigInvalidException e) {
        throw new ResourceConflictException(rsrc.getName(), e);
    }
    return Response.ok(getAccess.apply(rsrc.getNameKey()));
}
Also used : ProjectConfig(com.google.gerrit.server.project.ProjectConfig) ResourceConflictException(com.google.gerrit.extensions.restapi.ResourceConflictException) InvalidNameException(com.google.gerrit.exceptions.InvalidNameException) ConfigInvalidException(org.eclipse.jgit.errors.ConfigInvalidException) BadRequestException(com.google.gerrit.extensions.restapi.BadRequestException) AccessSection(com.google.gerrit.entities.AccessSection) MetaDataUpdate(com.google.gerrit.server.git.meta.MetaDataUpdate)

Example 14 with AccessSection

use of com.google.gerrit.entities.AccessSection in project gerrit by GerritCodeReview.

the class GetAccess method apply.

@Override
public Response<ProjectAccessInfo> apply(ProjectResource rsrc) throws ResourceNotFoundException, ResourceConflictException, IOException, PermissionBackendException {
    // Load the current configuration from the repository, ensuring it's the most
    // recent version available. If it differs from what was in the project
    // state, force a cache flush now.
    Project.NameKey projectName = rsrc.getNameKey();
    ProjectAccessInfo info = new ProjectAccessInfo();
    ProjectState projectState = projectCache.get(projectName).orElseThrow(illegalState(projectName));
    PermissionBackend.ForProject perm = permissionBackend.currentUser().project(projectName);
    ProjectConfig config;
    try (MetaDataUpdate md = metaDataUpdateFactory.get().create(projectName)) {
        config = projectConfigFactory.read(md);
        info.configWebLinks = new ArrayList<>();
        // config may have a null revision if the repo doesn't have its own refs/meta/config.
        if (config.getRevision() != null) {
            info.configWebLinks.addAll(webLinks.getFileHistoryLinks(projectName.get(), config.getRevision().getName(), ProjectConfig.PROJECT_CONFIG));
        }
        if (config.updateGroupNames(groupBackend)) {
            md.setMessage("Update group names\n");
            config.commit(md);
            projectCache.evictAndReindex(config.getProject());
            projectState = projectCache.get(projectName).orElseThrow(illegalState(projectName));
            perm = permissionBackend.currentUser().project(projectName);
        } else if (config.getRevision() != null && !config.getRevision().equals(projectState.getConfig().getRevision().orElse(null))) {
            projectCache.evictAndReindex(config.getProject());
            projectState = projectCache.get(projectName).orElseThrow(illegalState(projectName));
            perm = permissionBackend.currentUser().project(projectName);
        }
    } catch (ConfigInvalidException e) {
        throw new ResourceConflictException(e.getMessage());
    } catch (RepositoryNotFoundException e) {
        throw new ResourceNotFoundException(rsrc.getName(), e);
    }
    // The following implementation must match the ProjectAccessFactory JSON RPC endpoint.
    info.local = new HashMap<>();
    info.ownerOf = new HashSet<>();
    Map<AccountGroup.UUID, GroupInfo> groups = new HashMap<>();
    boolean canReadConfig = check(perm, RefNames.REFS_CONFIG, READ);
    boolean canWriteConfig = check(perm, ProjectPermission.WRITE_CONFIG);
    // config to set the project state to any state that is not HIDDEN.
    if (!canWriteConfig) {
        projectState.checkStatePermitsRead();
    }
    for (AccessSection section : config.getAccessSections()) {
        String name = section.getName();
        if (AccessSection.GLOBAL_CAPABILITIES.equals(name)) {
            if (canWriteConfig) {
                info.local.put(name, createAccessSection(groups, section));
                info.ownerOf.add(name);
            } else if (canReadConfig) {
                info.local.put(section.getName(), createAccessSection(groups, section));
            }
        } else if (AccessSection.isValidRefSectionName(name)) {
            if (check(perm, name, WRITE_CONFIG)) {
                info.local.put(name, createAccessSection(groups, section));
                info.ownerOf.add(name);
            } else if (canReadConfig) {
                info.local.put(name, createAccessSection(groups, section));
            } else if (check(perm, name, READ)) {
                // Filter the section to only add rules describing groups that
                // are visible to the current-user. This includes any group the
                // user is a member of, as well as groups they own or that
                // are visible to all users.
                AccessSection.Builder dst = null;
                for (Permission srcPerm : section.getPermissions()) {
                    Permission.Builder dstPerm = null;
                    for (PermissionRule srcRule : srcPerm.getRules()) {
                        AccountGroup.UUID groupId = srcRule.getGroup().getUUID();
                        if (groupId == null) {
                            continue;
                        }
                        loadGroup(groups, groupId);
                        if (dstPerm == null) {
                            if (dst == null) {
                                dst = AccessSection.builder(name);
                                info.local.put(name, createAccessSection(groups, dst.build()));
                            }
                            dstPerm = dst.upsertPermission(srcPerm.getName());
                        }
                        dstPerm.add(srcRule.toBuilder());
                    }
                }
            }
        }
    }
    if (info.ownerOf.isEmpty()) {
        try {
            permissionBackend.currentUser().check(GlobalPermission.ADMINISTRATE_SERVER);
            // Special case: If the section list is empty, this project has no current
            // access control information. Fall back to site administrators.
            info.ownerOf.add(AccessSection.ALL);
        } catch (AuthException e) {
        // Do nothing.
        }
    }
    if (config.getRevision() != null) {
        info.revision = config.getRevision().name();
    }
    ProjectState parent = Iterables.getFirst(projectState.parents(), null);
    if (parent != null) {
        info.inheritsFrom = projectJson.format(parent.getProject());
    }
    if (projectName.equals(allProjectsName) && permissionBackend.currentUser().testOrFalse(ADMINISTRATE_SERVER)) {
        info.ownerOf.add(AccessSection.GLOBAL_CAPABILITIES);
    }
    info.isOwner = toBoolean(canWriteConfig);
    info.canUpload = toBoolean(projectState.statePermitsWrite() && (canWriteConfig || (canReadConfig && perm.ref(RefNames.REFS_CONFIG).testOrFalse(CREATE_CHANGE))));
    info.canAdd = toBoolean(perm.testOrFalse(CREATE_REF));
    info.canAddTags = toBoolean(perm.testOrFalse(CREATE_TAG_REF));
    info.configVisible = canReadConfig || canWriteConfig;
    info.groups = groups.entrySet().stream().filter(e -> e.getValue() != null).collect(toMap(e -> e.getKey().get(), Map.Entry::getValue));
    return Response.ok(info);
}
Also used : ConfigInvalidException(org.eclipse.jgit.errors.ConfigInvalidException) PermissionBackend(com.google.gerrit.server.permissions.PermissionBackend) HashMap(java.util.HashMap) PermissionRule(com.google.gerrit.entities.PermissionRule) ProjectAccessInfo(com.google.gerrit.extensions.api.access.ProjectAccessInfo) AuthException(com.google.gerrit.extensions.restapi.AuthException) RefPermission(com.google.gerrit.server.permissions.RefPermission) GlobalPermission(com.google.gerrit.server.permissions.GlobalPermission) ProjectPermission(com.google.gerrit.server.permissions.ProjectPermission) Permission(com.google.gerrit.entities.Permission) ResourceNotFoundException(com.google.gerrit.extensions.restapi.ResourceNotFoundException) GroupInfo(com.google.gerrit.extensions.common.GroupInfo) RepositoryNotFoundException(org.eclipse.jgit.errors.RepositoryNotFoundException) AccessSection(com.google.gerrit.entities.AccessSection) ProjectConfig(com.google.gerrit.server.project.ProjectConfig) Project(com.google.gerrit.entities.Project) ResourceConflictException(com.google.gerrit.extensions.restapi.ResourceConflictException) ProjectState(com.google.gerrit.server.project.ProjectState) MetaDataUpdate(com.google.gerrit.server.git.meta.MetaDataUpdate)

Example 15 with AccessSection

use of com.google.gerrit.entities.AccessSection in project gerrit by GerritCodeReview.

the class CreateAccessChange method apply.

@Override
public Response<ChangeInfo> apply(ProjectResource rsrc, ProjectAccessInput input) throws PermissionBackendException, AuthException, IOException, ConfigInvalidException, InvalidNameException, UpdateException, RestApiException {
    PermissionBackend.ForProject forProject = permissionBackend.user(rsrc.getUser()).project(rsrc.getNameKey());
    if (!check(forProject, ProjectPermission.READ_CONFIG)) {
        throw new AuthException(RefNames.REFS_CONFIG + " not visible");
    }
    if (!check(forProject, ProjectPermission.WRITE_CONFIG)) {
        try {
            forProject.ref(RefNames.REFS_CONFIG).check(RefPermission.CREATE_CHANGE);
        } catch (AuthException denied) {
            throw new AuthException("cannot create change for " + RefNames.REFS_CONFIG, denied);
        }
    }
    projectCache.get(rsrc.getNameKey()).orElseThrow(illegalState(rsrc.getNameKey())).checkStatePermitsWrite();
    MetaDataUpdate.User metaDataUpdateUser = metaDataUpdateFactory.get();
    ImmutableList<AccessSection> removals = setAccess.getAccessSections(input.remove);
    ImmutableList<AccessSection> additions = setAccess.getAccessSections(input.add);
    Project.NameKey newParentProjectName = input.parent == null ? null : Project.nameKey(input.parent);
    try (MetaDataUpdate md = metaDataUpdateUser.create(rsrc.getNameKey())) {
        ProjectConfig config = projectConfigFactory.read(md);
        ObjectId oldCommit = config.getRevision();
        String oldCommitSha1 = oldCommit == null ? null : oldCommit.getName();
        setAccess.validateChanges(config, removals, additions);
        setAccess.applyChanges(config, removals, additions);
        try {
            setAccess.setParentName(rsrc.getUser().asIdentifiedUser(), config, rsrc.getNameKey(), newParentProjectName, false);
        } catch (AuthException e) {
            throw new IllegalStateException(e);
        }
        md.setMessage("Review access change");
        md.setInsertChangeId(true);
        Change.Id changeId = Change.id(seq.nextChangeId());
        RevCommit commit = config.commitToNewRef(md, PatchSet.id(changeId, Change.INITIAL_PATCH_SET_ID).toRefName());
        if (commit.name().equals(oldCommitSha1)) {
            throw new BadRequestException("no change");
        }
        try (ObjectInserter objInserter = md.getRepository().newObjectInserter();
            ObjectReader objReader = objInserter.newReader();
            RevWalk rw = new RevWalk(objReader);
            BatchUpdate bu = updateFactory.create(rsrc.getNameKey(), rsrc.getUser(), TimeUtil.now())) {
            bu.setRepository(md.getRepository(), rw, objInserter);
            ChangeInserter ins = newInserter(changeId, commit);
            bu.insertChange(ins);
            bu.execute();
            return Response.created(jsonFactory.noOptions().format(ins.getChange()));
        }
    } catch (InvalidNameException e) {
        throw new BadRequestException(e.toString());
    }
}
Also used : PermissionBackend(com.google.gerrit.server.permissions.PermissionBackend) ObjectId(org.eclipse.jgit.lib.ObjectId) AuthException(com.google.gerrit.extensions.restapi.AuthException) Change(com.google.gerrit.entities.Change) RevWalk(org.eclipse.jgit.revwalk.RevWalk) AccessSection(com.google.gerrit.entities.AccessSection) BatchUpdate(com.google.gerrit.server.update.BatchUpdate) ProjectConfig(com.google.gerrit.server.project.ProjectConfig) Project(com.google.gerrit.entities.Project) ObjectInserter(org.eclipse.jgit.lib.ObjectInserter) InvalidNameException(com.google.gerrit.exceptions.InvalidNameException) BadRequestException(com.google.gerrit.extensions.restapi.BadRequestException) ObjectReader(org.eclipse.jgit.lib.ObjectReader) ChangeInserter(com.google.gerrit.server.change.ChangeInserter) MetaDataUpdate(com.google.gerrit.server.git.meta.MetaDataUpdate) RevCommit(org.eclipse.jgit.revwalk.RevCommit)

Aggregations

AccessSection (com.google.gerrit.entities.AccessSection)22 Permission (com.google.gerrit.entities.Permission)16 PermissionRule (com.google.gerrit.entities.PermissionRule)7 MetaDataUpdate (com.google.gerrit.server.git.meta.MetaDataUpdate)6 ProjectConfig (com.google.gerrit.server.project.ProjectConfig)6 ArrayList (java.util.ArrayList)5 HashSet (java.util.HashSet)5 Test (org.junit.Test)5 ConfigInvalidException (org.eclipse.jgit.errors.ConfigInvalidException)4 Project (com.google.gerrit.entities.Project)3 InvalidNameException (com.google.gerrit.exceptions.InvalidNameException)3 CoreOrPluginProjectPermission (com.google.gerrit.extensions.api.access.CoreOrPluginProjectPermission)3 PluginProjectPermission (com.google.gerrit.extensions.api.access.PluginProjectPermission)3 BadRequestException (com.google.gerrit.extensions.restapi.BadRequestException)3 SectionMatcher (com.google.gerrit.server.project.SectionMatcher)3 ImmutableList (com.google.common.collect.ImmutableList)2 AbstractDaemonTest (com.google.gerrit.acceptance.AbstractDaemonTest)2 GroupDescription (com.google.gerrit.entities.GroupDescription)2 GroupReference (com.google.gerrit.entities.GroupReference)2 LabelType (com.google.gerrit.entities.LabelType)2