Skip to content

Commit 6f66cd7

Browse files
authored
Merge pull request #154 from devcordde/appliation-size-validation
Appliation size validation
2 parents 1d3c97b + 1e6779e commit 6f66cd7

10 files changed

Lines changed: 62 additions & 9 deletions

File tree

backend/build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ plugins {
33
id("io.micronaut.application") version "3.5.1"
44
}
55

6-
version = "1.0"
6+
version = "2.0"
77
group = "club.devcord.devmarkt"
88

99
repositories {
@@ -32,7 +32,7 @@ dependencies {
3232
implementation("io.micronaut.data:micronaut-data-jdbc")
3333
implementation("io.micronaut.flyway:micronaut-flyway")
3434
implementation("io.micronaut.graphql:micronaut-graphql")
35-
implementation("com.graphql-java-kickstart:graphql-java-tools:13.0.0")
35+
implementation("com.graphql-java-kickstart:graphql-java-tools:12.1.0")
3636
implementation("com.graphql-java:graphql-java-extended-validation:18.1-hibernate-validator-6.2.0.Final")
3737
implementation("io.micronaut:micronaut-validation")
3838
runtimeOnly("org.postgresql:postgresql")

backend/src/main/java/club/devcord/devmarkt/responses/failure/application/ErrorCode.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,6 @@ public enum ErrorCode implements club.devcord.devmarkt.responses.failure.ErrorCo
2626
NO_QUESTION,
2727
ANSWER_TOO_SHORT,
2828
ALREADY_ACCEPTED,
29-
QUESTION_UNANSWERED
29+
QUESTION_UNANSWERED,
30+
TOO_LARGE
3031
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright 2022 Contributors to the Devmarkt-Backend project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package club.devcord.devmarkt.responses.failure.application;
18+
19+
import club.devcord.devmarkt.entities.application.Application;
20+
import club.devcord.devmarkt.graphql.GraphQLType;
21+
import club.devcord.devmarkt.responses.failure.ErrorData;
22+
23+
@GraphQLType
24+
public record TooLargeErrorData(
25+
int size
26+
) implements ErrorData<Application> {
27+
28+
}

backend/src/main/java/club/devcord/devmarkt/services/ApplicationService.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import club.devcord.devmarkt.responses.failure.application.AnswerTooShortApplicationErrorData;
3232
import club.devcord.devmarkt.responses.failure.application.ErrorCode;
3333
import club.devcord.devmarkt.responses.failure.application.NumberApplicationErrorData;
34+
import club.devcord.devmarkt.responses.failure.application.TooLargeErrorData;
3435
import jakarta.inject.Singleton;
3536
import java.util.ArrayList;
3637
import java.util.Collection;
@@ -110,8 +111,9 @@ public Application createApplication(String templateName, ArrayList<Answer> answ
110111
throw new FailureException(ErrorCode.TEMPLATE_NOT_FOUND);
111112
}
112113

113-
var errors = new ArrayList<Error<Application>>();
114114
var template = templateOpt.get();
115+
var errors = new ArrayList<Error<Application>>();
116+
validateSize(template, answers, errors);
115117
validateAndPrepareAnswers(answers, template, answer -> null, null, errors, true);
116118

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

130+
// according to the discord embed limits -> https://discordjs.guide/popular-topics/embeds.html#embed-limits
131+
private void validateSize(Template template, List<Answer> answers, ArrayList<Error<Application>> errors) {
132+
var size = template.name().length();
133+
for (var question : template.questions()) {
134+
size += question.question().length();
135+
}
136+
for (var answer : answers) {
137+
size += answer.answer().length();
138+
}
139+
140+
if (size > 5800) { // leave 200 chars for extra text
141+
errors.add(new Error<>(ErrorCode.TOO_LARGE, new TooLargeErrorData(size)));
142+
}
143+
}
144+
128145
private void validateAndPrepareAnswers(ArrayList<Answer> answers,
129146
Template template, Function<Answer, Integer> numberFunc, Application application,
130147
Collection<Error<Application>> errors, boolean checkUnansweredQuestions) {

backend/src/main/resources/graphql/schemas/application.graphql

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
input AnswerInput {
22
number: NonNegativeInt!
3-
answer: String! @NotBlank
3+
answer: String! @NotBlank @Size(min: 1, max: 1024)
44
}
55

66
type Answer {
@@ -25,6 +25,10 @@ type AnswerTooShortApplicationErrorData {
2525
number: NonNegativeInt!
2626
}
2727

28+
type TooLargeErrorData {
29+
size: Int
30+
}
31+
2832
union ApplicationResponse = Application | Failure
2933

3034
type Application {

backend/src/main/resources/graphql/schemas/common.graphql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ type Query {
1919
type Mutation {
2020
createTemplate(
2121
name: TemplateName!
22-
questions: [QuestionInput!]!
22+
questions: [QuestionInput!]! @ContainerSize(min: 1, max: 25)
2323
): TemplateResponse @Auth(role: "admin")
2424

2525
deleteTemplate(

backend/src/main/resources/graphql/schemas/failure.graphql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
union FailureData = NumberTemplateErrorData | NumberApplicationErrorData | AnswerTooShortApplicationErrorData
1+
union FailureData = NumberTemplateErrorData | NumberApplicationErrorData | AnswerTooShortApplicationErrorData | TooLargeErrorData
22

33
type Failure {
44
errors: [Error!]!

backend/src/main/resources/graphql/schemas/misc.graphql

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION
1010
directive @Range(min: Int = 0, max: Int = 2147483647, message: String = "graphql.validation.Range.message")
1111
on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION
1212

13+
directive @ContainerSize(min: Int = 0, max: Int = 2147483647, message: String = "graphql.validation.ContainerSize.message")
14+
on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION
15+
1316
directive @Auth(role: String!) on FIELD_DEFINITION
1417
directive @AuthOwnApplication(idField: String!) on FIELD_DEFINITION # user must own application or be admin
1518

backend/src/main/resources/graphql/schemas/question.graphql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
input QuestionInput {
2-
question: String! @NotBlank @Size(min: 1, max: 200)
2+
question: String! @NotBlank @Size(min: 1, max: 256)
33
number: NonNegativeInt!
44
multiline: Boolean!
55
minAnswerLength: Int! = 1 @Range(min: 1, max: 1024)

qa/src/spec/template.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ const tests = [
6969
name: 'duplicated',
7070
query: 'template/create-template.graphql',
7171
response: 'template/create-duplicated.json',
72-
variables: {name: 'Dev searched', questions: []},
72+
variables: templateCreateVars("Dev searched"),
7373
verify: {
7474
query: "template/templates.graphql",
7575
response: "template/templates.json"

0 commit comments

Comments
 (0)