Skip to content

Commit

Permalink
Merge pull request #154 from devcordde/appliation-size-validation
Browse files Browse the repository at this point in the history
Appliation size validation
  • Loading branch information
Goldmensch authored Aug 26, 2022
2 parents 1d3c97b + 1e6779e commit 6f66cd7
Show file tree
Hide file tree
Showing 10 changed files with 62 additions and 9 deletions.
4 changes: 2 additions & 2 deletions backend/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ plugins {
id("io.micronaut.application") version "3.5.1"
}

version = "1.0"
version = "2.0"
group = "club.devcord.devmarkt"

repositories {
Expand Down Expand Up @@ -32,7 +32,7 @@ dependencies {
implementation("io.micronaut.data:micronaut-data-jdbc")
implementation("io.micronaut.flyway:micronaut-flyway")
implementation("io.micronaut.graphql:micronaut-graphql")
implementation("com.graphql-java-kickstart:graphql-java-tools:13.0.0")
implementation("com.graphql-java-kickstart:graphql-java-tools:12.1.0")
implementation("com.graphql-java:graphql-java-extended-validation:18.1-hibernate-validator-6.2.0.Final")
implementation("io.micronaut:micronaut-validation")
runtimeOnly("org.postgresql:postgresql")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,6 @@ public enum ErrorCode implements club.devcord.devmarkt.responses.failure.ErrorCo
NO_QUESTION,
ANSWER_TOO_SHORT,
ALREADY_ACCEPTED,
QUESTION_UNANSWERED
QUESTION_UNANSWERED,
TOO_LARGE
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright 2022 Contributors to the Devmarkt-Backend project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package club.devcord.devmarkt.responses.failure.application;

import club.devcord.devmarkt.entities.application.Application;
import club.devcord.devmarkt.graphql.GraphQLType;
import club.devcord.devmarkt.responses.failure.ErrorData;

@GraphQLType
public record TooLargeErrorData(
int size
) implements ErrorData<Application> {

}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import club.devcord.devmarkt.responses.failure.application.AnswerTooShortApplicationErrorData;
import club.devcord.devmarkt.responses.failure.application.ErrorCode;
import club.devcord.devmarkt.responses.failure.application.NumberApplicationErrorData;
import club.devcord.devmarkt.responses.failure.application.TooLargeErrorData;
import jakarta.inject.Singleton;
import java.util.ArrayList;
import java.util.Collection;
Expand Down Expand Up @@ -110,8 +111,9 @@ public Application createApplication(String templateName, ArrayList<Answer> answ
throw new FailureException(ErrorCode.TEMPLATE_NOT_FOUND);
}

var errors = new ArrayList<Error<Application>>();
var template = templateOpt.get();
var errors = new ArrayList<Error<Application>>();
validateSize(template, answers, errors);
validateAndPrepareAnswers(answers, template, answer -> null, null, errors, true);

if (!errors.isEmpty()) {
Expand All @@ -125,6 +127,21 @@ public Application createApplication(String templateName, ArrayList<Answer> answ
return saved;
}

// according to the discord embed limits -> https://discordjs.guide/popular-topics/embeds.html#embed-limits
private void validateSize(Template template, List<Answer> answers, ArrayList<Error<Application>> errors) {
var size = template.name().length();
for (var question : template.questions()) {
size += question.question().length();
}
for (var answer : answers) {
size += answer.answer().length();
}

if (size > 5800) { // leave 200 chars for extra text
errors.add(new Error<>(ErrorCode.TOO_LARGE, new TooLargeErrorData(size)));
}
}

private void validateAndPrepareAnswers(ArrayList<Answer> answers,
Template template, Function<Answer, Integer> numberFunc, Application application,
Collection<Error<Application>> errors, boolean checkUnansweredQuestions) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
input AnswerInput {
number: NonNegativeInt!
answer: String! @NotBlank
answer: String! @NotBlank @Size(min: 1, max: 1024)
}

type Answer {
Expand All @@ -25,6 +25,10 @@ type AnswerTooShortApplicationErrorData {
number: NonNegativeInt!
}

type TooLargeErrorData {
size: Int
}

union ApplicationResponse = Application | Failure

type Application {
Expand Down
2 changes: 1 addition & 1 deletion backend/src/main/resources/graphql/schemas/common.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type Query {
type Mutation {
createTemplate(
name: TemplateName!
questions: [QuestionInput!]!
questions: [QuestionInput!]! @ContainerSize(min: 1, max: 25)
): TemplateResponse @Auth(role: "admin")

deleteTemplate(
Expand Down
2 changes: 1 addition & 1 deletion backend/src/main/resources/graphql/schemas/failure.graphql
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
union FailureData = NumberTemplateErrorData | NumberApplicationErrorData | AnswerTooShortApplicationErrorData
union FailureData = NumberTemplateErrorData | NumberApplicationErrorData | AnswerTooShortApplicationErrorData | TooLargeErrorData

type Failure {
errors: [Error!]!
Expand Down
3 changes: 3 additions & 0 deletions backend/src/main/resources/graphql/schemas/misc.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION
directive @Range(min: Int = 0, max: Int = 2147483647, message: String = "graphql.validation.Range.message")
on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION

directive @ContainerSize(min: Int = 0, max: Int = 2147483647, message: String = "graphql.validation.ContainerSize.message")
on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION

directive @Auth(role: String!) on FIELD_DEFINITION
directive @AuthOwnApplication(idField: String!) on FIELD_DEFINITION # user must own application or be admin

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
input QuestionInput {
question: String! @NotBlank @Size(min: 1, max: 200)
question: String! @NotBlank @Size(min: 1, max: 256)
number: NonNegativeInt!
multiline: Boolean!
minAnswerLength: Int! = 1 @Range(min: 1, max: 1024)
Expand Down
2 changes: 1 addition & 1 deletion qa/src/spec/template.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ const tests = [
name: 'duplicated',
query: 'template/create-template.graphql',
response: 'template/create-duplicated.json',
variables: {name: 'Dev searched', questions: []},
variables: templateCreateVars("Dev searched"),
verify: {
query: "template/templates.graphql",
response: "template/templates.json"
Expand Down

0 comments on commit 6f66cd7

Please sign in to comment.