Skip to content

Commit

Permalink
closes #144: limit max documents in insert many (#315)
Browse files Browse the repository at this point in the history
  • Loading branch information
Ivan Senic authored Mar 30, 2023
1 parent 685b15d commit d2176cb
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.fasterxml.jackson.databind.JsonNode;
import io.stargate.sgv2.jsonapi.api.model.command.Command;
import io.stargate.sgv2.jsonapi.api.model.command.ModifyCommand;
import io.stargate.sgv2.jsonapi.api.model.command.validation.MaxInsertManyDocuments;
import java.util.List;
import javax.annotation.Nullable;
import javax.validation.constraints.NotEmpty;
Expand All @@ -22,6 +23,7 @@
public record InsertManyCommand(
@NotNull
@NotEmpty
@MaxInsertManyDocuments
@Schema(
description = "JSON document to insert.",
implementation = Object.class,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package io.stargate.sgv2.jsonapi.api.model.command.validation;

import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import io.stargate.sgv2.jsonapi.config.DocumentLimitsConfig;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;

/**
* Limits the maximum amount of documents to insert, as defined in the {@link DocumentLimitsConfig}.
*/
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
@Retention(RUNTIME)
@Constraint(validatedBy = {MaxInsertManyDocumentsValidation.class})
public @interface MaxInsertManyDocuments {

String message() default "amount of documents to insert is over the max limit";

Class<?>[] groups() default {};

Class<? extends Payload>[] payload() default {};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package io.stargate.sgv2.jsonapi.api.model.command.validation;

import com.fasterxml.jackson.databind.JsonNode;
import java.util.List;
import javax.enterprise.context.ApplicationScoped;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import org.eclipse.microprofile.config.inject.ConfigProperty;

/** Validator for the {@link MaxInsertManyDocuments} annotation. */
@ApplicationScoped
public class MaxInsertManyDocumentsValidation
implements ConstraintValidator<MaxInsertManyDocuments, List<JsonNode>> {

private final int limit;

// due to https://github.com/quarkusio/quarkus/issues/32265
// I can only inject prop, not the whole config class
public MaxInsertManyDocumentsValidation(
@ConfigProperty(name = "stargate.jsonapi.doc-limits.max-insert-many-documents") int limit) {
this.limit = limit;
}

/** {@inheritDoc} */
@Override
public boolean isValid(List<JsonNode> value, ConstraintValidatorContext context) {
return null != value && value.size() <= limit;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,20 @@ public interface DocumentLimitsConfig {
@WithDefault("64")
int maxObjectProperties();

/** @return Defines the maximum length of , defaults to {@code 8 levels} */
/** @return Defines the maximum length of a single String value. */
@Positive
@WithDefault("16000")
int maxStringLength();

/** @return Maximum length of an array. */
@Positive
@WithDefault("100")
int maxArrayLength();

/**
* @return Maximum amount of documents that can be inserted using <code>insertMany</code> command.
*/
// keep in sync with MaxInsertManyDocumentsValidation
@Positive
int maxInsertManyDocuments();
}
5 changes: 5 additions & 0 deletions src/main/resources/application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ stargate:
global-tags:
module: sgv2-jsonapi

# explicitly set limits
jsonapi:
doc-limits:
max-insert-many-documents: 20

quarkus:

# general app properties
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import io.quarkus.test.junit.QuarkusTest;
import io.quarkus.test.junit.TestProfile;
import io.stargate.sgv2.common.testprofiles.NoGlobalResourcesTestProfile;
import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
import javax.validation.ConstraintViolation;
Expand All @@ -14,9 +15,17 @@
import org.junit.jupiter.api.Test;

@QuarkusTest
@TestProfile(NoGlobalResourcesTestProfile.Impl.class)
@TestProfile(InsertManyCommandTest.Profile.class)
class InsertManyCommandTest {

public static class Profile implements NoGlobalResourcesTestProfile {

@Override
public Map<String, String> getConfigOverrides() {
return Map.of("stargate.jsonapi.doc-limits.max-insert-many-documents", "2");
}
}

@Inject ObjectMapper objectMapper;

@Inject Validator validator;
Expand Down Expand Up @@ -62,5 +71,49 @@ public void documentsArrayEmpty() throws Exception {
.extracting(ConstraintViolation::getMessage)
.contains("must not be empty");
}

@Test
public void tooManyDocuments() throws Exception {
String json =
"""
{
"insertMany": {
"documents": [
{},
{},
{}
]
}
}
""";

InsertManyCommand command = objectMapper.readValue(json, InsertManyCommand.class);
Set<ConstraintViolation<InsertManyCommand>> result = validator.validate(command);

assertThat(result)
.isNotEmpty()
.extracting(ConstraintViolation::getMessage)
.contains("amount of documents to insert is over the max limit");
}

@Test
public void acceptableDocuments() throws Exception {
String json =
"""
{
"insertMany": {
"documents": [
{},
{}
]
}
}
""";

InsertManyCommand command = objectMapper.readValue(json, InsertManyCommand.class);
Set<ConstraintViolation<InsertManyCommand>> result = validator.validate(command);

assertThat(result).isEmpty();
}
}
}

0 comments on commit d2176cb

Please sign in to comment.