Search in sources :

Example 46 with UnprocessableEntityException

use of com.google.gerrit.extensions.restapi.UnprocessableEntityException in project gerrit by GerritCodeReview.

the class ChangeInserter method updateChange.

@Override
public boolean updateChange(ChangeContext ctx) throws RestApiException, IOException, PermissionBackendException, ConfigInvalidException {
    // Use defensive copy created by ChangeControl.
    change = ctx.getChange();
    patchSetInfo = patchSetInfoFactory.get(ctx.getRevWalk(), ctx.getRevWalk().parseCommit(commitId), psId);
    ctx.getChange().setCurrentPatchSet(patchSetInfo);
    ChangeUpdate update = ctx.getUpdate(psId);
    update.setChangeId(change.getKey().get());
    update.setSubjectForCommit("Create change");
    update.setBranch(change.getDest().branch());
    try {
        update.setTopic(change.getTopic());
    } catch (ValidationException ex) {
        throw new BadRequestException(ex.getMessage());
    }
    update.setPsDescription(patchSetDescription);
    update.setPrivate(isPrivate);
    update.setWorkInProgress(workInProgress);
    if (revertOf != null) {
        update.setRevertOf(revertOf.get());
    }
    if (cherryPickOf != null) {
        update.setCherryPickOf(cherryPickOf.getCommaSeparatedChangeAndPatchSetId());
    }
    List<String> newGroups = groups;
    if (newGroups.isEmpty()) {
        newGroups = GroupCollector.getDefaultGroups(commitId);
    }
    patchSet = psUtil.insert(ctx.getRevWalk(), update, psId, commitId, newGroups, pushCert, patchSetDescription);
    /* TODO: fixStatusToMerged is used here because the tests
     * (byStatusClosed() in AbstractQueryChangesTest)
     * insert changes that are already merged,
     * and setStatus may not be used to set the Status to merged
     *
     * is it possible to make the tests use the merge code path,
     * instead of setting the status directly?
     */
    if (change.getStatus() == Change.Status.MERGED) {
        update.fixStatusToMerged(new SubmissionId(change));
    } else {
        update.setStatus(change.getStatus());
    }
    reviewerAdditions = reviewerModifier.prepare(ctx.getNotes(), ctx.getUser(), getReviewerInputs(), true);
    Optional<ReviewerModification> reviewerError = reviewerAdditions.getFailures().stream().findFirst();
    if (reviewerError.isPresent()) {
        throw new UnprocessableEntityException(reviewerError.get().result.error);
    }
    reviewerAdditions.updateChange(ctx, patchSet);
    LabelTypes labelTypes = projectState.getLabelTypes();
    approvalsUtil.addApprovalsForNewPatchSet(update, labelTypes, patchSet, ctx.getUser(), approvals);
    // TODO(dborowitz): Still necessary?
    if (!approvals.isEmpty()) {
        update.putReviewer(ctx.getAccountId(), REVIEWER);
    }
    if (message != null) {
        changeMessage = cmUtil.setChangeMessage(update, message, ChangeMessagesUtil.uploadedPatchSetTag(workInProgress));
    }
    return true;
}
Also used : UnprocessableEntityException(com.google.gerrit.extensions.restapi.UnprocessableEntityException) LabelTypes(com.google.gerrit.entities.LabelTypes) CommitValidationException(com.google.gerrit.server.git.validators.CommitValidationException) ValidationException(com.google.gerrit.server.validators.ValidationException) SubmissionId(com.google.gerrit.entities.SubmissionId) BadRequestException(com.google.gerrit.extensions.restapi.BadRequestException) ReviewerModification(com.google.gerrit.server.change.ReviewerModifier.ReviewerModification) ChangeUpdate(com.google.gerrit.server.notedb.ChangeUpdate)

Example 47 with UnprocessableEntityException

use of com.google.gerrit.extensions.restapi.UnprocessableEntityException in project gerrit by GerritCodeReview.

the class ProjectsConsistencyChecker method checkForAutoCloseableChanges.

private AutoCloseableChangesCheckResult checkForAutoCloseableChanges(Project.NameKey projectName, AutoCloseableChangesCheckInput input) throws IOException, RestApiException {
    AutoCloseableChangesCheckResult r = new AutoCloseableChangesCheckResult();
    if (Strings.isNullOrEmpty(input.branch)) {
        throw new BadRequestException("branch is required");
    }
    boolean fix = input.fix != null ? input.fix : false;
    if (input.maxCommits != null && input.maxCommits > AUTO_CLOSE_MAX_COMMITS_LIMIT) {
        throw new BadRequestException("max commits can at most be set to " + AUTO_CLOSE_MAX_COMMITS_LIMIT);
    }
    int maxCommits = input.maxCommits != null ? input.maxCommits : AUTO_CLOSE_MAX_COMMITS_LIMIT;
    // Result that we want to return to the client.
    List<ChangeInfo> autoCloseableChanges = new ArrayList<>();
    // Remember the change IDs of all changes that we already included into the result, so that we
    // can avoid including the same change twice.
    Set<Change.Id> seenChanges = new HashSet<>();
    try (Repository repo = repoManager.openRepository(projectName);
        RevWalk rw = new RevWalk(repo)) {
        String branch = RefNames.fullName(input.branch);
        Ref ref = repo.exactRef(branch);
        if (ref == null) {
            throw new UnprocessableEntityException(String.format("branch '%s' not found", input.branch));
        }
        rw.reset();
        rw.markStart(rw.parseCommit(ref.getObjectId()));
        rw.sort(RevSort.TOPO);
        rw.sort(RevSort.REVERSE);
        // Cache the SHA1's of all merged commits. We need this for knowing which commit merged the
        // change when auto-closing changes by commit.
        List<ObjectId> mergedSha1s = new ArrayList<>();
        // Cache the Change-Id to commit SHA1 mapping for all Change-Id's that we find in merged
        // commits. We need this for knowing which commit merged the change when auto-closing
        // changes by Change-Id.
        Map<Change.Key, ObjectId> changeIdToMergedSha1 = new HashMap<>();
        // Base predicate which is fixed for every change query.
        Predicate<ChangeData> basePredicate = and(ChangePredicates.project(projectName), ChangePredicates.ref(branch), open());
        int maxLeafPredicates = indexConfig.maxTerms() - basePredicate.getLeafCount();
        // List of predicates by which we want to find open changes for the branch. These predicates
        // will be combined with the 'or' operator.
        List<Predicate<ChangeData>> predicates = new ArrayList<>(maxLeafPredicates);
        RevCommit commit;
        int skippedCommits = 0;
        int walkedCommits = 0;
        while ((commit = rw.next()) != null) {
            if (input.skipCommits != null && skippedCommits < input.skipCommits) {
                skippedCommits++;
                continue;
            }
            if (walkedCommits >= maxCommits) {
                break;
            }
            walkedCommits++;
            ObjectId commitId = commit.copy();
            mergedSha1s.add(commitId);
            // Consider all Change-Id lines since this is what ReceiveCommits#autoCloseChanges does.
            List<String> changeIds = ChangeUtil.getChangeIdsFromFooter(commit, urlFormatter.get());
            // Number of predicates that we need to add for this commit, 1 per Change-Id plus one for
            // the commit.
            int newPredicatesCount = changeIds.size() + 1;
            // the query and start a new one.
            if (predicates.size() + newPredicatesCount > maxLeafPredicates) {
                autoCloseableChanges.addAll(executeQueryAndAutoCloseChanges(basePredicate, seenChanges, predicates, fix, changeIdToMergedSha1, mergedSha1s));
                mergedSha1s.clear();
                changeIdToMergedSha1.clear();
                predicates.clear();
                if (newPredicatesCount > maxLeafPredicates) {
                    // Whee, a single commit generates more than maxLeafPredicates predicates. Give up.
                    throw new ResourceConflictException(String.format("commit %s contains more Change-Ids than we can handle", commit.name()));
                }
            }
            changeIds.forEach(changeId -> {
                // It can happen that there are multiple merged commits with the same Change-Id
                // footer (e.g. if a change was cherry-picked to a stable branch stable branch which
                // then got merged back into master, or just by directly pushing several commits
                // with the same Change-Id). In this case it is hard to say which of the commits
                // should be used to auto-close an open change with the same Change-Id (and branch).
                // Possible approaches are:
                // 1. use the oldest commit with that Change-Id to auto-close the change
                // 2. use the newest commit with that Change-Id to auto-close the change
                // Possibility 1. has the disadvantage that the commit may have been merged before
                // the change was created in which case it is strange how it could auto-close the
                // change. Also this strategy would require to walk all commits since otherwise we
                // cannot be sure that we have seen the oldest commit with that Change-Id.
                // Possibility 2 has the disadvantage that it doesn't produce the same result as if
                // auto-closing on push would have worked, since on direct push the first commit with
                // a Change-Id of an open change would have closed that change. Also for this we
                // would need to consider all commits that are skipped.
                // Since both possibilities are not perfect and require extra effort we choose the
                // easiest approach, which is use the newest commit with that Change-Id that we have
                // seen (this means we ignore skipped commits). This should be okay since the
                // important thing for callers is that auto-closable changes are closed. Which of the
                // commits is used to auto-close a change if there are several candidates is of minor
                // importance and hence can be non-deterministic.
                Change.Key changeKey = Change.key(changeId);
                if (!changeIdToMergedSha1.containsKey(changeKey)) {
                    changeIdToMergedSha1.put(changeKey, commitId);
                }
                // Find changes that have a matching Change-Id.
                predicates.add(ChangePredicates.idPrefix(changeId));
            });
            // Find changes that have a matching commit.
            predicates.add(ChangePredicates.commitPrefix(commit.name()));
        }
        if (!predicates.isEmpty()) {
            // Execute the query with the remaining predicates that were collected.
            autoCloseableChanges.addAll(executeQueryAndAutoCloseChanges(basePredicate, seenChanges, predicates, fix, changeIdToMergedSha1, mergedSha1s));
        }
    }
    r.autoCloseableChanges = autoCloseableChanges;
    return r;
}
Also used : HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Predicate(com.google.gerrit.index.query.Predicate) HashSet(java.util.HashSet) RevCommit(org.eclipse.jgit.revwalk.RevCommit) UnprocessableEntityException(com.google.gerrit.extensions.restapi.UnprocessableEntityException) ChangeInfo(com.google.gerrit.extensions.common.ChangeInfo) ObjectId(org.eclipse.jgit.lib.ObjectId) Change(com.google.gerrit.entities.Change) RevWalk(org.eclipse.jgit.revwalk.RevWalk) ChangeData(com.google.gerrit.server.query.change.ChangeData) Repository(org.eclipse.jgit.lib.Repository) Ref(org.eclipse.jgit.lib.Ref) ResourceConflictException(com.google.gerrit.extensions.restapi.ResourceConflictException) BadRequestException(com.google.gerrit.extensions.restapi.BadRequestException) ObjectId(org.eclipse.jgit.lib.ObjectId) AutoCloseableChangesCheckResult(com.google.gerrit.extensions.api.projects.CheckProjectResultInfo.AutoCloseableChangesCheckResult)

Example 48 with UnprocessableEntityException

use of com.google.gerrit.extensions.restapi.UnprocessableEntityException in project gerrit by GerritCodeReview.

the class AddMembers method apply.

@Override
public Response<List<AccountInfo>> apply(GroupResource resource, Input input) throws AuthException, NotInternalGroupException, UnprocessableEntityException, IOException, ConfigInvalidException, ResourceNotFoundException, PermissionBackendException {
    GroupDescription.Internal internalGroup = resource.asInternalGroup().orElseThrow(NotInternalGroupException::new);
    input = Input.init(input);
    GroupControl control = resource.getControl();
    if (!control.canAddMember()) {
        throw new AuthException("Cannot add members to group " + internalGroup.getName());
    }
    Set<Account.Id> newMemberIds = new LinkedHashSet<>();
    for (String nameOrEmailOrId : input.members) {
        Account a = findAccount(nameOrEmailOrId);
        if (!a.isActive()) {
            throw new UnprocessableEntityException(String.format("Account Inactive: %s", nameOrEmailOrId));
        }
        newMemberIds.add(a.id());
    }
    AccountGroup.UUID groupUuid = internalGroup.getGroupUUID();
    try {
        addMembers(groupUuid, newMemberIds);
    } catch (NoSuchGroupException e) {
        throw new ResourceNotFoundException(String.format("Group %s not found", groupUuid), e);
    }
    return Response.ok(toAccountInfoList(newMemberIds));
}
Also used : LinkedHashSet(java.util.LinkedHashSet) Account(com.google.gerrit.entities.Account) UnprocessableEntityException(com.google.gerrit.extensions.restapi.UnprocessableEntityException) AuthException(com.google.gerrit.extensions.restapi.AuthException) IdString(com.google.gerrit.extensions.restapi.IdString) NoSuchGroupException(com.google.gerrit.exceptions.NoSuchGroupException) GroupDescription(com.google.gerrit.entities.GroupDescription) GroupControl(com.google.gerrit.server.account.GroupControl) AccountGroup(com.google.gerrit.entities.AccountGroup) ExternalId(com.google.gerrit.server.account.externalids.ExternalId) ResourceNotFoundException(com.google.gerrit.extensions.restapi.ResourceNotFoundException)

Example 49 with UnprocessableEntityException

use of com.google.gerrit.extensions.restapi.UnprocessableEntityException in project gerrit by GerritCodeReview.

the class ConfirmEmail method apply.

@Override
public Response<?> apply(ConfigResource rsrc, Input input) throws AuthException, UnprocessableEntityException, IOException, ConfigInvalidException {
    CurrentUser user = self.get();
    if (!user.isIdentifiedUser()) {
        throw new AuthException("Authentication required");
    }
    if (input == null) {
        input = new Input();
    }
    if (input.token == null) {
        throw new UnprocessableEntityException("missing token");
    }
    try {
        EmailTokenVerifier.ParsedToken token = emailTokenVerifier.decode(input.token);
        Account.Id accId = user.getAccountId();
        if (accId.equals(token.getAccountId())) {
            accountManager.link(accId, token.toAuthRequest());
            return Response.none();
        }
        throw new UnprocessableEntityException("invalid token");
    } catch (EmailTokenVerifier.InvalidTokenException e) {
        throw new UnprocessableEntityException("invalid token", e);
    } catch (AccountException e) {
        throw new UnprocessableEntityException(e.getMessage());
    }
}
Also used : UnprocessableEntityException(com.google.gerrit.extensions.restapi.UnprocessableEntityException) Account(com.google.gerrit.entities.Account) Input(com.google.gerrit.server.restapi.config.ConfirmEmail.Input) DefaultInput(com.google.gerrit.extensions.restapi.DefaultInput) EmailTokenVerifier(com.google.gerrit.server.mail.EmailTokenVerifier) CurrentUser(com.google.gerrit.server.CurrentUser) AccountException(com.google.gerrit.server.account.AccountException) AuthException(com.google.gerrit.extensions.restapi.AuthException)

Example 50 with UnprocessableEntityException

use of com.google.gerrit.extensions.restapi.UnprocessableEntityException 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)

Aggregations

UnprocessableEntityException (com.google.gerrit.extensions.restapi.UnprocessableEntityException)78 AuthException (com.google.gerrit.extensions.restapi.AuthException)31 BadRequestException (com.google.gerrit.extensions.restapi.BadRequestException)27 ResourceConflictException (com.google.gerrit.extensions.restapi.ResourceConflictException)25 AbstractDaemonTest (com.google.gerrit.acceptance.AbstractDaemonTest)23 Test (org.junit.Test)23 IOException (java.io.IOException)13 ArrayList (java.util.ArrayList)13 Account (com.google.gerrit.entities.Account)12 Ref (org.eclipse.jgit.lib.Ref)10 PushOneCommit (com.google.gerrit.acceptance.PushOneCommit)9 CurrentUser (com.google.gerrit.server.CurrentUser)9 IdentifiedUser (com.google.gerrit.server.IdentifiedUser)9 PermissionBackend (com.google.gerrit.server.permissions.PermissionBackend)9 ConfigInvalidException (org.eclipse.jgit.errors.ConfigInvalidException)9 ResourceNotFoundException (com.google.gerrit.extensions.restapi.ResourceNotFoundException)8 Map (java.util.Map)8 ObjectId (org.eclipse.jgit.lib.ObjectId)8 RevCommit (org.eclipse.jgit.revwalk.RevCommit)8 Nullable (com.google.gerrit.common.Nullable)7