package de.iwomm.propify_api.controller; import de.iwomm.propify_api.dto.BulkDeletePropertyIdsDTO; import de.iwomm.propify_api.dto.PropertyDTO; import de.iwomm.propify_api.entity.Attachment; import de.iwomm.propify_api.entity.Property; import de.iwomm.propify_api.s3.S3Service; import de.iwomm.propify_api.s3.UploadResponse; import de.iwomm.propify_api.service.AttachmentService; import de.iwomm.propify_api.service.PropertyService; import jakarta.persistence.EntityNotFoundException; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.servlet.support.ServletUriComponentsBuilder; import java.io.IOException; import java.net.URI; import java.util.*; @RestController @RequestMapping("/api/v1/properties") public class PropertyController { private final PropertyService propertyService; private final AttachmentService attachmentService; private final S3Service s3service; public PropertyController(PropertyService propertyService, AttachmentService attachmentService, S3Service s3Service) { this.propertyService = propertyService; this.attachmentService = attachmentService; this.s3service = s3Service; } @GetMapping @PreAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_USER')") public ResponseEntity getAll() { List propertiesDTO = propertyService.toDTOs(propertyService.findAll()); return ResponseEntity .ok(propertiesDTO); } @GetMapping("/{id}") @PreAuthorize("hasAnyRole('ADMIN', 'USER')") public ResponseEntity getById(@PathVariable UUID id) { try { return ResponseEntity .ok(propertyService.findById(id).orElseThrow(EntityNotFoundException::new)); } catch (EntityNotFoundException e) { return ResponseEntity .notFound() .build(); } catch (Exception e) { return ResponseEntity .internalServerError() .build(); } } @PostMapping("/{id}/upload") @PreAuthorize("hasRole('ADMIN')") public ResponseEntity upload(@RequestParam("attachments") List files, @PathVariable UUID id) { List messages = new ArrayList<>(); if (files.isEmpty()) { return ResponseEntity .ok() .body(new UploadResponse(HttpStatus.BAD_REQUEST, "No attachments provided.")); } Property property; try { property = propertyService.findById(id).orElseThrow(EntityNotFoundException::new); } catch (EntityNotFoundException e) { return ResponseEntity .unprocessableEntity() .build(); } files.forEach(file -> { String originalFileName = file.getOriginalFilename(); String uniqueFileName = id + "/" + UUID.randomUUID() + "_" + originalFileName; try { s3service.putObject("skamp", uniqueFileName, file); Attachment newAttachment = new Attachment(); newAttachment.setProperty(property); newAttachment.setStoragePath(uniqueFileName); newAttachment.setFileName(originalFileName); this.attachmentService.save(newAttachment); property.getAttachments().add(newAttachment); messages.add("Successfully uploaded " + originalFileName + " to " + uniqueFileName); } catch (IOException e) { messages.add("Failed uploading " + originalFileName); } }); propertyService.save(property); return ResponseEntity.ok(new UploadResponse(HttpStatus.OK, messages)); } @PostMapping @PreAuthorize("hasRole('ADMIN')") public ResponseEntity create(@RequestBody PropertyDTO propertyDTO) { try { Property newItem = propertyService.saveDTO(propertyDTO); URI location = ServletUriComponentsBuilder.fromCurrentRequest() .path("/{id}") .buildAndExpand(newItem.getId()) .toUri(); return ResponseEntity .created(location) .body(newItem); } catch (Exception e) { return ResponseEntity .internalServerError() .build(); } } @PatchMapping("/{id}") @PreAuthorize("hasRole('ADMIN')") public ResponseEntity update(@PathVariable UUID id, @RequestBody PropertyDTO propertyDTO) { try { return ResponseEntity .ok(propertyService.update(id, propertyDTO)); } catch (EntityNotFoundException e) { return ResponseEntity .notFound() .build(); } catch (Exception e) { return ResponseEntity .internalServerError() .build(); } } @DeleteMapping("/{id}") @PreAuthorize("hasRole('ADMIN')") public ResponseEntity delete(@PathVariable UUID id) { try { propertyService.deleteById(id); return ResponseEntity .noContent() .build(); } catch (EntityNotFoundException e) { return ResponseEntity .notFound() .build(); } catch (Exception e) { return ResponseEntity .internalServerError() .build(); } } @PostMapping("/bulk-delete") @PreAuthorize("hasRole('ADMIN')") public ResponseEntity deleteMany(@RequestBody BulkDeletePropertyIdsDTO propertiesDTO) { try { propertyService.deleteByIds(propertiesDTO); return ResponseEntity .noContent() .build(); } catch (EntityNotFoundException e) { return ResponseEntity .notFound() .build(); } catch (Exception e) { return ResponseEntity .internalServerError() .build(); } } }