fix validation bugs
This commit is contained in:
@@ -309,17 +309,18 @@ public class AuthController {
|
||||
public ResponseEntity<Resource> getAvatarFile() {
|
||||
User user = authHelper.getAuthenticatedUser();
|
||||
|
||||
if (!avatarStorageService.hasAvatar(user)) {
|
||||
return ResponseEntity.notFound().build();
|
||||
if (avatarStorageService.hasAvatar(user)) {
|
||||
try {
|
||||
Resource resource = avatarStorageService.loadAvatarResource(user);
|
||||
MediaType mediaType = avatarStorageService.resolveMediaType(user);
|
||||
return ResponseEntity.ok().contentType(mediaType).body(resource);
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
Resource resource = avatarStorageService.loadAvatarResource(user);
|
||||
MediaType mediaType = avatarStorageService.resolveMediaType(user);
|
||||
return ResponseEntity.ok().contentType(mediaType).body(resource);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
return ResponseEntity.ok()
|
||||
.contentType(MediaType.valueOf("image/svg+xml"))
|
||||
.body(avatarStorageService.loadDefaultAvatarResource());
|
||||
}
|
||||
|
||||
@DeleteMapping("/me/avatar")
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.petshop.backend.repository.UserRepository;
|
||||
import com.petshop.backend.service.AvatarStorageService;
|
||||
import com.petshop.backend.util.ImageValidationUtil;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
@@ -42,18 +43,23 @@ public class UserAvatarController {
|
||||
@PreAuthorize("isAuthenticated()")
|
||||
public ResponseEntity<Resource> getUserAvatarFile(@PathVariable Long userId) {
|
||||
User user = userRepository.findById(userId).orElse(null);
|
||||
if (user == null || !avatarStorageService.hasAvatar(user)) {
|
||||
if (user == null) {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
try {
|
||||
Resource resource = avatarStorageService.loadAvatarResource(user);
|
||||
return ResponseEntity.ok()
|
||||
.contentType(avatarStorageService.resolveMediaType(user))
|
||||
.body(resource);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
return ResponseEntity.notFound().build();
|
||||
if (avatarStorageService.hasAvatar(user)) {
|
||||
try {
|
||||
Resource resource = avatarStorageService.loadAvatarResource(user);
|
||||
return ResponseEntity.ok()
|
||||
.contentType(avatarStorageService.resolveMediaType(user))
|
||||
.body(resource);
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
return ResponseEntity.ok()
|
||||
.contentType(MediaType.valueOf("image/svg+xml"))
|
||||
.body(avatarStorageService.loadDefaultAvatarResource());
|
||||
}
|
||||
|
||||
@PostMapping("/{userId}/avatar")
|
||||
|
||||
@@ -143,7 +143,7 @@ public class AppointmentService {
|
||||
appointment.setEmployee(employee);
|
||||
appointment.setAppointmentDate(request.getAppointmentDate());
|
||||
appointment.setAppointmentTime(request.getAppointmentTime());
|
||||
appointment.setAppointmentStatus(request.getAppointmentStatus());
|
||||
appointment.setAppointmentStatus("Scheduled");
|
||||
appointment.setPet(pet);
|
||||
|
||||
appointment = appointmentRepository.save(appointment);
|
||||
@@ -304,11 +304,9 @@ public class AppointmentService {
|
||||
}
|
||||
|
||||
private void validateAppointmentRequest(AppointmentRequest request) {
|
||||
if ("Booked".equalsIgnoreCase(request.getAppointmentStatus())) {
|
||||
LocalDateTime appointmentDateTime = LocalDateTime.of(request.getAppointmentDate(), request.getAppointmentTime());
|
||||
if (appointmentDateTime.isBefore(LocalDateTime.now())) {
|
||||
throw new BusinessException("Booked appointments must be scheduled in the future");
|
||||
}
|
||||
LocalDateTime appointmentDateTime = LocalDateTime.of(request.getAppointmentDate(), request.getAppointmentTime());
|
||||
if (appointmentDateTime.isBefore(LocalDateTime.now())) {
|
||||
throw new BusinessException("Appointments must be scheduled in the future");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
@@ -54,7 +55,11 @@ public class AvatarStorageService {
|
||||
public Resource loadAvatarResource(User user) {
|
||||
String filename = extractFilename(user.getAvatarUrl());
|
||||
if (blobService.isEnabled()) {
|
||||
return new ByteArrayResource(blobService.download(BLOB_CONTAINER, filename));
|
||||
try {
|
||||
return new ByteArrayResource(blobService.download(BLOB_CONTAINER, filename));
|
||||
} catch (Exception ex) {
|
||||
throw new IllegalArgumentException("Avatar file was not found");
|
||||
}
|
||||
}
|
||||
Path filePath = resolveStoredAvatarPath(user.getAvatarUrl());
|
||||
if (!Files.exists(filePath) || !Files.isRegularFile(filePath)) {
|
||||
@@ -63,6 +68,18 @@ public class AvatarStorageService {
|
||||
return new PathResource(filePath);
|
||||
}
|
||||
|
||||
public Resource loadDefaultAvatarResource() {
|
||||
InputStream is = getClass().getResourceAsStream("/static/default-avatar.svg");
|
||||
if (is == null) {
|
||||
throw new IllegalStateException("Default avatar resource not found");
|
||||
}
|
||||
try {
|
||||
return new ByteArrayResource(is.readAllBytes());
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException("Failed to read default avatar", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteAvatar(User user) throws IOException {
|
||||
if (user.getAvatarUrl() == null || user.getAvatarUrl().isBlank()) return;
|
||||
if (blobService.isEnabled()) {
|
||||
@@ -80,7 +97,7 @@ public class AvatarStorageService {
|
||||
}
|
||||
|
||||
public String toOwnerAvatarUrl(User user) {
|
||||
return hasAvatar(user) ? "/api/v1/users/" + user.getId() + "/avatar/file" : null;
|
||||
return "/api/v1/users/" + user.getId() + "/avatar/file";
|
||||
}
|
||||
|
||||
public String toStoredAvatarUrl(String avatarFilenamePath) {
|
||||
|
||||
@@ -146,6 +146,12 @@ public class ChatService {
|
||||
}
|
||||
}
|
||||
|
||||
boolean hasContent = request.getContent() != null && !request.getContent().isBlank();
|
||||
boolean hasAttachment = request.getAttachmentUrl() != null && !request.getAttachmentUrl().isBlank();
|
||||
if (!hasContent && !hasAttachment) {
|
||||
throw new BusinessException("Message must have content or an attachment");
|
||||
}
|
||||
|
||||
ContentFilter.validate(request.getContent());
|
||||
|
||||
Message message = new Message();
|
||||
|
||||
@@ -89,6 +89,10 @@ public class CouponService {
|
||||
}
|
||||
|
||||
private void updateCouponFields(Coupon coupon, CouponRequest request) {
|
||||
if ("PERCENTAGE".equalsIgnoreCase(request.getDiscountType())
|
||||
&& request.getDiscountValue().compareTo(new BigDecimal("100")) >= 0) {
|
||||
throw new BusinessException("Percentage discount must be less than 100");
|
||||
}
|
||||
coupon.setCouponCode(request.getCouponCode());
|
||||
coupon.setDiscountType(request.getDiscountType());
|
||||
coupon.setDiscountValue(request.getDiscountValue());
|
||||
|
||||
1
backend/src/main/resources/static/default-avatar.svg
Normal file
1
backend/src/main/resources/static/default-avatar.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" width="128" height="128"><circle cx="64" cy="64" r="64" fill="#9e9e9e"/><circle cx="64" cy="50" r="22" fill="#fff"/><ellipse cx="64" cy="114" rx="40" ry="36" fill="#fff"/></svg>
|
||||
|
After Width: | Height: | Size: 240 B |
Reference in New Issue
Block a user