Merge branch 'feat/configure-input-length' into sattelgeschichten
# Conflicts: # src/main/java/net/javahippie/fitpub/controller/ActivitiesViewController.java # src/main/java/net/javahippie/fitpub/controller/ActivityController.java # src/main/java/net/javahippie/fitpub/controller/ProfileViewController.java # src/main/java/net/javahippie/fitpub/controller/UserController.java
This commit is contained in:
commit
1ecd6c8765
8 changed files with 176 additions and 22 deletions
|
|
@ -10,6 +10,7 @@ import org.apache.hc.client5.http.io.HttpClientConnectionManager;
|
|||
import org.apache.hc.core5.util.Timeout;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
|
|
@ -22,6 +23,7 @@ import org.springframework.web.client.RestTemplate;
|
|||
* through the ActivityPub protocol.
|
||||
*/
|
||||
@SpringBootApplication
|
||||
@ConfigurationPropertiesScan
|
||||
@EnableAsync
|
||||
@EnableScheduling
|
||||
@Slf4j
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
package net.javahippie.fitpub.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Configurable max-length limits for user and activity text fields.
|
||||
*/
|
||||
@Data
|
||||
@ConfigurationProperties(prefix = "fitpub")
|
||||
public class FitPubTextLimitsProperties {
|
||||
|
||||
private User user = new User();
|
||||
private Activity activity = new Activity();
|
||||
|
||||
@Data
|
||||
public static class User {
|
||||
private Bio bio = new Bio();
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class Bio {
|
||||
private int maxLength = 500;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class Activity {
|
||||
private Title title = new Title();
|
||||
private Description description = new Description();
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class Title {
|
||||
private int maxLength = 200;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class Description {
|
||||
private int maxLength = 5000;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,7 @@
|
|||
package net.javahippie.fitpub.controller;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import net.javahippie.fitpub.service.ActivityDescriptionValidationService;
|
||||
import net.javahippie.fitpub.service.ActivityTitleValidationService;
|
||||
import net.javahippie.fitpub.service.TextValidationService;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
|
@ -17,8 +16,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
|||
@RequiredArgsConstructor
|
||||
public class ActivitiesViewController {
|
||||
|
||||
private final ActivityDescriptionValidationService activityDescriptionValidationService;
|
||||
private final ActivityTitleValidationService activityTitleValidationService;
|
||||
private final TextValidationService textValidationService;
|
||||
|
||||
/**
|
||||
* Show activities list page
|
||||
|
|
@ -33,8 +31,8 @@ public class ActivitiesViewController {
|
|||
*/
|
||||
@GetMapping("/upload")
|
||||
public String uploadActivity(Model model) {
|
||||
model.addAttribute("activityTitleMaxLength", activityTitleValidationService.getMaxLength());
|
||||
model.addAttribute("activityDescriptionMaxLength", activityDescriptionValidationService.getMaxLength());
|
||||
model.addAttribute("activityTitleMaxLength", textValidationService.getActivityTitleMaxLength());
|
||||
model.addAttribute("activityDescriptionMaxLength", textValidationService.getActivityDescriptionMaxLength());
|
||||
return "activities/upload";
|
||||
}
|
||||
|
||||
|
|
@ -53,8 +51,8 @@ public class ActivitiesViewController {
|
|||
@GetMapping("/{id}/edit")
|
||||
public String editActivity(@PathVariable String id, Model model) {
|
||||
// The activity data will be loaded via JavaScript API calls
|
||||
model.addAttribute("activityTitleMaxLength", activityTitleValidationService.getMaxLength());
|
||||
model.addAttribute("activityDescriptionMaxLength", activityDescriptionValidationService.getMaxLength());
|
||||
model.addAttribute("activityTitleMaxLength", textValidationService.getActivityTitleMaxLength());
|
||||
model.addAttribute("activityDescriptionMaxLength", textValidationService.getActivityDescriptionMaxLength());
|
||||
return "activities/edit";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,16 +13,15 @@ import net.javahippie.fitpub.model.entity.PrivacyZone;
|
|||
import net.javahippie.fitpub.model.entity.User;
|
||||
import net.javahippie.fitpub.repository.FollowRepository;
|
||||
import net.javahippie.fitpub.repository.UserRepository;
|
||||
import net.javahippie.fitpub.service.ActivityDescriptionValidationService;
|
||||
import net.javahippie.fitpub.service.ActivityFileService;
|
||||
import net.javahippie.fitpub.service.ActivityImageService;
|
||||
import net.javahippie.fitpub.service.ActivityPostProcessingService;
|
||||
import net.javahippie.fitpub.service.ActivityTitleValidationService;
|
||||
import net.javahippie.fitpub.service.FederationService;
|
||||
import net.javahippie.fitpub.service.WeatherService;
|
||||
import net.javahippie.fitpub.service.FitFileService;
|
||||
import net.javahippie.fitpub.service.PrivacyZoneService;
|
||||
import net.javahippie.fitpub.service.ReactionEnricher;
|
||||
import net.javahippie.fitpub.service.TextValidationService;
|
||||
import net.javahippie.fitpub.service.TrackPrivacyFilter;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
|
@ -50,8 +49,7 @@ import java.util.UUID;
|
|||
@Slf4j
|
||||
public class ActivityController {
|
||||
|
||||
private final ActivityDescriptionValidationService activityDescriptionValidationService;
|
||||
private final ActivityTitleValidationService activityTitleValidationService;
|
||||
private final TextValidationService textValidationService;
|
||||
private final ActivityFileService activityFileService;
|
||||
private final FitFileService fitFileService;
|
||||
private final UserRepository userRepository;
|
||||
|
|
@ -157,8 +155,8 @@ public class ActivityController {
|
|||
) {
|
||||
log.info("User {} uploading activity file: {}", userDetails.getUsername(), file.getOriginalFilename());
|
||||
|
||||
activityTitleValidationService.validate(request.getTitle());
|
||||
activityDescriptionValidationService.validate(request.getDescription());
|
||||
textValidationService.validateActivityTitle(request.getTitle());
|
||||
textValidationService.validateActivityDescription(request.getDescription());
|
||||
|
||||
User user = userRepository.findByUsername(userDetails.getUsername())
|
||||
.orElseThrow(() -> new UsernameNotFoundException("User not found"));
|
||||
|
|
@ -318,8 +316,8 @@ public class ActivityController {
|
|||
|
||||
UUID userId = getUserId(userDetails);
|
||||
|
||||
activityTitleValidationService.validate(request.getTitle());
|
||||
activityDescriptionValidationService.validate(request.getDescription());
|
||||
textValidationService.validateActivityTitle(request.getTitle());
|
||||
textValidationService.validateActivityDescription(request.getDescription());
|
||||
|
||||
try {
|
||||
Activity updated = fitFileService.updateActivity(
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package net.javahippie.fitpub.controller;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import net.javahippie.fitpub.service.UserBioValidationService;
|
||||
import net.javahippie.fitpub.service.TextValidationService;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
|
@ -14,7 +14,7 @@ import org.springframework.web.bind.annotation.PathVariable;
|
|||
@RequiredArgsConstructor
|
||||
public class ProfileViewController {
|
||||
|
||||
private final UserBioValidationService userBioValidationService;
|
||||
private final TextValidationService textValidationService;
|
||||
|
||||
/**
|
||||
* Current user's profile page.
|
||||
|
|
@ -39,7 +39,7 @@ public class ProfileViewController {
|
|||
@GetMapping("/profile/edit")
|
||||
public String editProfile(Model model) {
|
||||
model.addAttribute("pageTitle", "Edit Profile");
|
||||
model.addAttribute("bioMaxLength", userBioValidationService.getMaxLength());
|
||||
model.addAttribute("bioMaxLength", textValidationService.getUserBioMaxLength());
|
||||
return "profile/edit";
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ import net.javahippie.fitpub.repository.FollowRepository;
|
|||
import net.javahippie.fitpub.repository.RemoteActorRepository;
|
||||
import net.javahippie.fitpub.repository.UserRepository;
|
||||
import net.javahippie.fitpub.service.FederationService;
|
||||
import net.javahippie.fitpub.service.TextValidationService;
|
||||
import net.javahippie.fitpub.service.WebFingerClient;
|
||||
import net.javahippie.fitpub.service.UserBioValidationService;
|
||||
import net.javahippie.fitpub.service.UserService;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.data.domain.Page;
|
||||
|
|
@ -48,7 +48,7 @@ public class UserController {
|
|||
private final WebFingerClient webFingerClient;
|
||||
private final FederationService federationService;
|
||||
private final UserService userService;
|
||||
private final UserBioValidationService userBioValidationService;
|
||||
private final TextValidationService textValidationService;
|
||||
private final net.javahippie.fitpub.repository.ActivityPeakRepository activityPeakRepository;
|
||||
|
||||
@Value("${fitpub.base-url}")
|
||||
|
|
@ -103,7 +103,7 @@ public class UserController {
|
|||
) {
|
||||
log.info("User {} updating profile", userDetails.getUsername());
|
||||
|
||||
userBioValidationService.validate(request.getBio());
|
||||
textValidationService.validateUserBio(request.getBio());
|
||||
|
||||
User user = userRepository.findByUsername(userDetails.getUsername())
|
||||
.orElseThrow(() -> new UsernameNotFoundException("User not found"));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
package net.javahippie.fitpub.service;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import net.javahippie.fitpub.config.FitPubTextLimitsProperties;
|
||||
import net.javahippie.fitpub.exception.ApiValidationException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* Central validation policy for configurable text fields.
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class TextValidationService {
|
||||
|
||||
private final FitPubTextLimitsProperties textLimitsProperties;
|
||||
|
||||
public int getUserBioMaxLength() {
|
||||
return textLimitsProperties.getUser().getBio().getMaxLength();
|
||||
}
|
||||
|
||||
public int getActivityTitleMaxLength() {
|
||||
return textLimitsProperties.getActivity().getTitle().getMaxLength();
|
||||
}
|
||||
|
||||
public int getActivityDescriptionMaxLength() {
|
||||
return textLimitsProperties.getActivity().getDescription().getMaxLength();
|
||||
}
|
||||
|
||||
public void validateUserBio(String bio) {
|
||||
validateMaxLength(bio, getUserBioMaxLength(), "Bio");
|
||||
}
|
||||
|
||||
public void validateActivityTitle(String title) {
|
||||
validateMaxLength(title, getActivityTitleMaxLength(), "Title");
|
||||
}
|
||||
|
||||
public void validateActivityDescription(String description) {
|
||||
validateMaxLength(description, getActivityDescriptionMaxLength(), "Description");
|
||||
}
|
||||
|
||||
private void validateMaxLength(String value, int maxLength, String fieldName) {
|
||||
if (value != null && value.length() > maxLength) {
|
||||
throw new ApiValidationException(fieldName + " must not exceed " + maxLength + " characters");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
package net.javahippie.fitpub.service;
|
||||
|
||||
import net.javahippie.fitpub.config.FitPubTextLimitsProperties;
|
||||
import net.javahippie.fitpub.exception.ApiValidationException;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
@DisplayName("TextValidationService Tests")
|
||||
class TextValidationServiceTest {
|
||||
|
||||
@Test
|
||||
@DisplayName("Should allow user bio up to configured max length")
|
||||
void shouldAllowUserBioUpToConfiguredMaxLength() {
|
||||
TextValidationService service = new TextValidationService(properties(12, 20, 30));
|
||||
|
||||
assertDoesNotThrow(() -> service.validateUserBio("123456789012"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should reject user bio longer than configured max length")
|
||||
void shouldRejectUserBioLongerThanConfiguredMaxLength() {
|
||||
TextValidationService service = new TextValidationService(properties(12, 20, 30));
|
||||
|
||||
assertThrows(ApiValidationException.class, () -> service.validateUserBio("1234567890123"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should allow activity title up to configured max length")
|
||||
void shouldAllowActivityTitleUpToConfiguredMaxLength() {
|
||||
TextValidationService service = new TextValidationService(properties(12, 10, 30));
|
||||
|
||||
assertDoesNotThrow(() -> service.validateActivityTitle("1234567890"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should reject activity title longer than configured max length")
|
||||
void shouldRejectActivityTitleLongerThanConfiguredMaxLength() {
|
||||
TextValidationService service = new TextValidationService(properties(12, 10, 30));
|
||||
|
||||
assertThrows(ApiValidationException.class, () -> service.validateActivityTitle("12345678901"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should allow activity description up to configured max length")
|
||||
void shouldAllowActivityDescriptionUpToConfiguredMaxLength() {
|
||||
TextValidationService service = new TextValidationService(properties(12, 10, 20));
|
||||
|
||||
assertDoesNotThrow(() -> service.validateActivityDescription("12345678901234567890"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Should reject activity description longer than configured max length")
|
||||
void shouldRejectActivityDescriptionLongerThanConfiguredMaxLength() {
|
||||
TextValidationService service = new TextValidationService(properties(12, 10, 20));
|
||||
|
||||
assertThrows(ApiValidationException.class, () -> service.validateActivityDescription("123456789012345678901"));
|
||||
}
|
||||
|
||||
private FitPubTextLimitsProperties properties(int bioMaxLength, int titleMaxLength, int descriptionMaxLength) {
|
||||
FitPubTextLimitsProperties properties = new FitPubTextLimitsProperties();
|
||||
properties.getUser().getBio().setMaxLength(bioMaxLength);
|
||||
properties.getActivity().getTitle().setMaxLength(titleMaxLength);
|
||||
properties.getActivity().getDescription().setMaxLength(descriptionMaxLength);
|
||||
return properties;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue