Skip to content

Commit 9a378b8

Browse files
committed
fix: validate the "comment" field for emptiness and max length
Fix #1411
1 parent 93e64fe commit 9a378b8

File tree

6 files changed

+68
-13
lines changed

6 files changed

+68
-13
lines changed

src/main/java/ru/mystamps/web/feature/series/RestSeriesController.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ class RestSeriesController {
4343

4444
private final SeriesService seriesService;
4545

46-
// @todo #785 Update series: add validation for a comment
4746
// @todo #1339 Update series: add validation for catalog numbers
4847
// @todo #1340 Update series: add validation for a price
4948
// @todo #1343 Update series: add validation for a release year
@@ -73,7 +72,7 @@ public ResponseEntity<Void> updateSeries(
7372
String path = patch.getPath();
7473
switch (path) {
7574
case "/comment":
76-
seriesService.addComment(seriesId, patch.getValue(), currentUserId);
75+
seriesService.addComment(seriesId, currentUserId, patch.getValue());
7776
break;
7877
case "/release_year":
7978
seriesService.addReleaseYear(seriesId, patch.integerValue(), currentUserId);

src/main/java/ru/mystamps/web/feature/series/SeriesService.java

+14-1
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,28 @@
1717
*/
1818
package ru.mystamps.web.feature.series;
1919

20+
import javax.validation.constraints.Size;
2021
import java.math.BigDecimal;
2122
import java.util.Date;
2223
import java.util.List;
2324

25+
import static ru.mystamps.web.feature.series.SeriesValidation.MAX_SERIES_COMMENT_LENGTH;
26+
2427
// FIXME: move stamps related methods to separate interface (#88)
2528
@SuppressWarnings("PMD.TooManyMethods")
2629
public interface SeriesService {
2730
Integer add(AddSeriesDto dto, Integer userId);
28-
void addComment(Integer seriesId, String comment, Integer userId);
31+
32+
// CheckStyle: ignore LineLength for next 6 lines
33+
// @todo #1411 Configure MethodValidationPostProcessor to use messages from ValidationMessages.properties
34+
void addComment(
35+
Integer seriesId,
36+
Integer userId,
37+
// @NotBlank isn't needed because PatchRequest.value has @NotEmpty and its setter trims blank values to null
38+
@Size(max = MAX_SERIES_COMMENT_LENGTH, message = "Value is greater than allowable maximum of {max} characters")
39+
String comment
40+
);
41+
2942
void addReleaseYear(Integer seriesId, Integer year, Integer userId);
3043
void addCatalogPrice(StampsCatalog catalog, Integer seriesId, BigDecimal price, Integer userId);
3144
void addCatalogNumbers(StampsCatalog catalog, Integer seriesId, String numbers, Integer userId);

src/main/java/ru/mystamps/web/feature/series/SeriesServiceImpl.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.slf4j.Logger;
2323
import org.springframework.security.access.prepost.PreAuthorize;
2424
import org.springframework.transaction.annotation.Transactional;
25+
import org.springframework.validation.annotation.Validated;
2526
import ru.mystamps.web.feature.image.ImageInfoDto;
2627
import ru.mystamps.web.feature.image.ImageService;
2728
import ru.mystamps.web.support.spring.security.HasAuthority;
@@ -38,6 +39,7 @@
3839
// The String literal "Series id must be non null" appears N times in this file
3940
// and we think that it's OK.
4041
@SuppressWarnings({ "PMD.TooManyMethods", "PMD.AvoidDuplicateLiterals" })
42+
@Validated
4143
@RequiredArgsConstructor
4244
public class SeriesServiceImpl implements SeriesService {
4345

@@ -115,11 +117,11 @@ public Integer add(AddSeriesDto dto, Integer userId) {
115117
@Override
116118
@Transactional
117119
@PreAuthorize(HasAuthority.ADD_COMMENTS_TO_SERIES)
118-
public void addComment(Integer seriesId, String comment, Integer userId) {
120+
public void addComment(Integer seriesId, Integer userId, String comment) {
119121
Validate.isTrue(seriesId != null, "Series id must be non null");
122+
Validate.isTrue(userId != null, "User id must be non null");
120123
Validate.isTrue(comment != null, "Comment must be non null");
121124
Validate.isTrue(!comment.trim().isEmpty(), "Comment must be non empty");
122-
Validate.isTrue(userId != null, "User id must be non null");
123125

124126
// We don't need to modify series.updated_at/updated_by fields because:
125127
// - a comment is a meta information that is invisible publicly

src/main/java/ru/mystamps/web/support/spring/mvc/ValidationErrors.java

+6-3
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,14 @@ private void extractFieldError(ConstraintViolation<?> violation) {
6060
// ValidationErrors
6161
Node last = getLastOrNull(violation.getPropertyPath());
6262
String name;
63-
if (last == null || last.getKind() != ElementKind.PROPERTY) {
63+
if (last != null && last.getKind() == ElementKind.PROPERTY) {
64+
name = last.getName();
65+
} else if (last != null && last.getKind() == ElementKind.PARAMETER) {
66+
// emulate validation of PatchRequest.value field
67+
name = "value";
68+
} else {
6469
// fallback to a field path for unsupported kinds
6570
name = violation.getPropertyPath().toString();
66-
} else {
67-
name = last.getName();
6871
}
6972

7073
String message = violation.getMessage();

src/test/groovy/ru/mystamps/web/feature/series/SeriesServiceImplTest.groovy

+5-5
Original file line numberDiff line numberDiff line change
@@ -439,31 +439,31 @@ class SeriesServiceImplTest extends Specification {
439439

440440
def 'addComment() should throw exception when series id is null'() {
441441
when:
442-
service.addComment(null, null, Random.userId())
442+
service.addComment(null, Random.userId(), 'text')
443443
then:
444444
IllegalArgumentException ex = thrown()
445445
ex.message == 'Series id must be non null'
446446
}
447447

448448
def 'addComment() should throw exception when comment is null'() {
449449
when:
450-
service.addComment(Random.id(), null, Random.userId())
450+
service.addComment(Random.id(), Random.userId(), null)
451451
then:
452452
IllegalArgumentException ex = thrown()
453453
ex.message == 'Comment must be non null'
454454
}
455455

456456
def 'addComment() should throw exception when comment is empty or blank'() {
457457
when:
458-
service.addComment(Random.id(), sample('', ' '), Random.userId())
458+
service.addComment(Random.id(), Random.userId(), sample('', ' '))
459459
then:
460460
IllegalArgumentException ex = thrown()
461461
ex.message == 'Comment must be non empty'
462462
}
463463

464464
def 'addComment() should throw exception when user id is null'() {
465465
when:
466-
service.addComment(Random.id(), 'a comment', null)
466+
service.addComment(Random.id(), null, 'a comment')
467467
then:
468468
IllegalArgumentException ex = thrown()
469469
ex.message == 'User id must be non null'
@@ -476,7 +476,7 @@ class SeriesServiceImplTest extends Specification {
476476
Integer expectedUserId = Random.userId()
477477
String expectedComment = 'this is important'
478478
when:
479-
service.addComment(expectedSeriesId, expectedComment, expectedUserId)
479+
service.addComment(expectedSeriesId, expectedUserId, expectedComment)
480480
then:
481481
1 * seriesDao.addComment({ AddCommentDbDto dto ->
482482
assert dto?.seriesId == expectedSeriesId
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
*** Settings ***
2+
Documentation Verify validation scenarios for adding a comment to a series
3+
Library SeleniumLibrary
4+
Resource ../../auth.steps.robot
5+
Resource ../../selenium.utils.robot
6+
Suite Setup Before Test Suite
7+
Suite Teardown Close Browser
8+
Force Tags series add-comment validation
9+
10+
*** Test Cases ***
11+
# In essence, here we test @NotEmpty annotation on PatchRequest.value because it validates an incoming value first
12+
Add comment with empty required field
13+
[Setup] Disable Client Validation add-comment-form
14+
Submit Form id:add-comment-form
15+
Wait Until Page Contains Element id:new-comment.errors
16+
Element Text Should Be id:new-comment.errors must not be empty
17+
18+
# In essence, here we test @NotEmpty annotation on PatchRequest.value and setValue() that trims blank values to null,
19+
# because it validates an incoming value first
20+
Add a blank comment
21+
Input Text id:new-comment ${SPACE}${SPACE}
22+
Submit Form id:add-comment-form
23+
Wait Until Page Contains Element id:new-comment.errors
24+
Element Text Should Be id:new-comment.errors must not be empty
25+
26+
Add too long comment
27+
${letter}= Set Variable x
28+
Input Text id:new-comment ${letter * 1025}
29+
Submit Form id:add-comment-form
30+
Wait Until Page Contains Element id:new-comment.errors
31+
Element Text Should Be id:new-comment.errors Value is greater than allowable maximum of 1024 characters
32+
33+
*** Keywords ***
34+
Before Test Suite
35+
Open Browser ${SITE_URL}/account/auth ${BROWSER}
36+
Register Keyword To Run On Failure Log Source
37+
Log In As login=coder password=test
38+
Go To ${SITE_URL}/series/5

0 commit comments

Comments
 (0)