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.git.validators; 16 : 17 : import com.google.common.collect.ImmutableList; 18 : import com.google.common.collect.Iterables; 19 : import com.google.gerrit.entities.Change; 20 : import com.google.gerrit.entities.Project; 21 : import com.google.gerrit.extensions.validators.CommentForValidation; 22 : import com.google.gerrit.extensions.validators.CommentValidationContext; 23 : import com.google.gerrit.extensions.validators.CommentValidationFailure; 24 : import com.google.gerrit.extensions.validators.CommentValidator; 25 : import com.google.gerrit.server.config.GerritServerConfig; 26 : import com.google.gerrit.server.notedb.ChangeNotes; 27 : import com.google.inject.Inject; 28 : import org.eclipse.jgit.lib.Config; 29 : 30 : /** Limits number of comments to prevent space/time complexity issues. */ 31 : public class CommentCountValidator implements CommentValidator { 32 : private final int maxComments; 33 : private final ChangeNotes.Factory notesFactory; 34 : 35 : @Inject 36 65 : CommentCountValidator(@GerritServerConfig Config serverConfig, ChangeNotes.Factory notesFactory) { 37 65 : this.notesFactory = notesFactory; 38 65 : maxComments = serverConfig.getInt("change", "maxComments", 5_000); 39 65 : } 40 : 41 : @Override 42 : public ImmutableList<CommentValidationFailure> validateComments( 43 : CommentValidationContext ctx, ImmutableList<CommentForValidation> comments) { 44 65 : ImmutableList.Builder<CommentValidationFailure> failures = ImmutableList.builder(); 45 65 : ChangeNotes notes = 46 65 : notesFactory.createChecked(Project.nameKey(ctx.getProject()), Change.id(ctx.getChangeId())); 47 65 : int numExistingCommentsAndChangeMessages = 48 65 : notes.getHumanComments().size() 49 65 : + notes.getRobotComments().size() 50 65 : + notes.getChangeMessages().size(); 51 65 : if (!comments.isEmpty() 52 65 : && numExistingCommentsAndChangeMessages + comments.size() > maxComments) { 53 : // This warning really applies to the set of all comments, but we need to pick one to attach 54 : // the message to. 55 3 : CommentForValidation commentForFailureMessage = Iterables.getLast(comments); 56 : 57 3 : failures.add( 58 3 : commentForFailureMessage.failValidation( 59 3 : String.format( 60 : "Exceeding maximum number of comments: %d (existing) + %d (new) > %d", 61 3 : numExistingCommentsAndChangeMessages, comments.size(), maxComments))); 62 : } 63 65 : return failures.build(); 64 : } 65 : }