user avatar in edit dialogs (#312)

This commit is contained in:
2026-04-15 15:58:46 -06:00
committed by GitHub
parent df5510224b
commit 2077c1b10c
10 changed files with 295 additions and 0 deletions

View File

@@ -4,12 +4,21 @@ import com.petshop.backend.entity.User;
import com.petshop.backend.repository.UserRepository;
import com.petshop.backend.service.AvatarStorageService;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/api/v1/users")
@@ -40,4 +49,70 @@ public class UserAvatarController {
return ResponseEntity.notFound().build();
}
}
@PostMapping("/{userId}/avatar")
@PreAuthorize("hasRole('ADMIN')")
public ResponseEntity<?> uploadUserAvatar(@PathVariable Long userId, @RequestParam("avatar") MultipartFile file) {
User user = userRepository.findById(userId).orElse(null);
if (user == null) {
return ResponseEntity.notFound().build();
}
if (file.isEmpty()) {
Map<String, String> error = new HashMap<>();
error.put("message", "Please select a file to upload");
return ResponseEntity.badRequest().body(error);
}
if (file.getSize() > 5 * 1024 * 1024) {
Map<String, String> error = new HashMap<>();
error.put("message", "File size must not exceed 5MB");
return ResponseEntity.badRequest().body(error);
}
String contentType = file.getContentType();
if (contentType == null || (!contentType.equals("image/jpeg") && !contentType.equals("image/png") && !contentType.equals("image/gif"))) {
Map<String, String> error = new HashMap<>();
error.put("message", "Only JPG, PNG, and GIF images are allowed");
return ResponseEntity.badRequest().body(error);
}
try {
avatarStorageService.deleteAvatar(user);
String avatarPath = avatarStorageService.storeAvatar(file);
user.setAvatarUrl(avatarPath);
userRepository.save(user);
Map<String, String> result = new HashMap<>();
result.put("avatarUrl", avatarStorageService.toOwnerAvatarUrl(user));
result.put("message", "Avatar uploaded successfully");
return ResponseEntity.ok(result);
} catch (IOException e) {
Map<String, String> error = new HashMap<>();
error.put("message", "Failed to upload avatar: " + e.getMessage());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);
}
}
@DeleteMapping("/{userId}/avatar")
@PreAuthorize("hasRole('ADMIN')")
public ResponseEntity<?> deleteUserAvatar(@PathVariable Long userId) {
User user = userRepository.findById(userId).orElse(null);
if (user == null) {
return ResponseEntity.notFound().build();
}
try {
avatarStorageService.deleteAvatar(user);
user.setAvatarUrl(null);
userRepository.save(user);
Map<String, String> result = new HashMap<>();
result.put("message", "Avatar removed successfully");
return ResponseEntity.ok(result);
} catch (IOException e) {
Map<String, String> error = new HashMap<>();
error.put("message", "Failed to remove avatar: " + e.getMessage());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);
}
}
}

View File

@@ -16,6 +16,7 @@ public class UserResponse {
private Long primaryStoreId;
private Integer loyaltyPoints;
private Boolean active;
private String avatarUrl;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
@@ -118,6 +119,14 @@ public class UserResponse {
this.active = active;
}
public String getAvatarUrl() {
return avatarUrl;
}
public void setAvatarUrl(String avatarUrl) {
this.avatarUrl = avatarUrl;
}
public LocalDateTime getCreatedAt() {
return createdAt;
}

View File

@@ -205,6 +205,7 @@ public class UserService {
response.setPrimaryStoreId(user.getPrimaryStore() != null ? user.getPrimaryStore().getStoreId() : null);
response.setLoyaltyPoints(user.getLoyaltyPoints());
response.setActive(user.getActive());
response.setAvatarUrl(user.getAvatarUrl() != null ? "/api/v1/users/" + user.getId() + "/avatar/file" : null);
response.setCreatedAt(user.getCreatedAt());
response.setUpdatedAt(user.getUpdatedAt());
return response;