FEAT : ajout de la suppression en cascade d'une photo (suppression de ses commentaires, partage, présence dans des albums, et du fichier /opt/........

This commit is contained in:
2025-12-03 14:36:52 +01:00
parent d26d3742c5
commit 96c060e206
12 changed files with 74 additions and 1 deletions

View File

@@ -163,7 +163,10 @@ public class PhotoController {
model.addAttribute("partages",
partageService.getPartagesForPhoto(id));
boolean isOwner = auth != null &&
photo.getProprietaire() != null &&
auth.getName().equals(photo.getProprietaire().getEmail());
model.addAttribute("isOwner", isOwner);
return "photo-detail";
}
@@ -230,6 +233,21 @@ public class PhotoController {
return ResponseEntity.ok().contentType(MediaType.IMAGE_JPEG).body(r);
}
/* ========================== SUPPRESSION PHOTO ========================== */
@PostMapping("/photo/{id}/delete")
@PreAuthorize("@securityService.canAccessPhoto(authentication, #id)")
public String deletePhoto(
@PathVariable Long id,
Authentication auth) {
PhotoDTO p = photoService.getPhotoById(id);
if (p == null || !p.getProprietaire().getEmail().equals(auth.getName())) {
return "redirect:/mes-photos?error=forbidden";
}
photoService.deletePhoto(id);
return "redirect:/mes-photos?deleted";
}
}

View File

@@ -44,6 +44,8 @@ public class Album {
private Set<Partage> partages = new HashSet<>();
public enum Visibilite {
PRIVATE,
SHARED,

View File

@@ -35,6 +35,9 @@ public class Photo {
@OneToMany(mappedBy = "photo", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<Partage> partages = new HashSet<>();
@OneToMany(mappedBy = "photo", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<Commentaire> commentaires = new HashSet<>();
@Column
private String uuidThumbnail;
}

View File

@@ -19,6 +19,8 @@ public interface PhotoService {
Page<PhotoDTO> listSharedWith(String email, int page, int size);
Page<PhotoDTO> listSharedPhotos(String email, int page, int size);
List<PhotoDTO> listAllPhotosOfUser(String email);
void deletePhoto(Long id);

View File

@@ -1,7 +1,9 @@
package local.epul4a.fotosharing.service.impl;
import jakarta.transaction.Transactional;
import local.epul4a.fotosharing.dto.PhotoDTO;
import local.epul4a.fotosharing.mapper.PhotoMapper;
import local.epul4a.fotosharing.model.Album;
import local.epul4a.fotosharing.model.Partage;
import local.epul4a.fotosharing.model.Photo;
import local.epul4a.fotosharing.model.Utilisateur;
@@ -185,4 +187,28 @@ public class PhotoServiceImpl implements PhotoService {
.toList();
}
//============= DELETE PHOTO =============================
@Override
@Transactional
public void deletePhoto(Long id) {
Photo photo = photoRepository.findById(id)
.orElseThrow(() -> new RuntimeException("Photo introuvable"));
//Retirer la photo de tous ses albums
for (Album album : photo.getAlbums()) {
album.getPhotos().remove(photo);
}
//Supprimer les fichiers (original + miniature)
try {
Path original = Paths.get(uploadDir).resolve(photo.getUuidFichier());
Path thumb = Paths.get(uploadDir).resolve(photo.getUuidThumbnail());
Files.deleteIfExists(original);
Files.deleteIfExists(thumb);
} catch (IOException ex) {
throw new RuntimeException("Erreur suppression fichiers", ex);
}
//Supprimer la photo en base & supprime aussi commentaires + partages via cascade
photoRepository.delete(photo);
}
}

View File

@@ -29,6 +29,17 @@
<li><strong>Visibilité :</strong> <span th:text="${photo.visibilite}"></span></li>
<li><strong>Propriétaire :</strong> <span th:text="${photo.proprietaire.email}"></span></li>
</ul>
<!-- Suppression de la photo par le propriétaire -->
<div th:if="${isOwner}">
<form th:action="@{'/photo/' + ${photo.id} + '/delete'}" method="post"
onsubmit="return confirm('Supprimer définitivement cette photo ?');">
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
<button type="submit" style="color:red; margin-bottom:20px;">
Supprimer la photo
</button>
</form>
</div>
<!-- Partage de la photo -->
<!-- Formulaire gestion visible uniquement en ADMIN ou PROPRIÉTAIRE -->

View File

@@ -29,6 +29,17 @@
<li><strong>Visibilité :</strong> <span th:text="${photo.visibilite}"></span></li>
<li><strong>Propriétaire :</strong> <span th:text="${photo.proprietaire.email}"></span></li>
</ul>
<!-- Suppression de la photo par le propriétaire -->
<div th:if="${isOwner}">
<form th:action="@{'/photo/' + ${photo.id} + '/delete'}" method="post"
onsubmit="return confirm('Supprimer définitivement cette photo ?');">
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
<button type="submit" style="color:red; margin-bottom:20px;">
Supprimer la photo
</button>
</form>
</div>
<!-- Partage de la photo -->
<!-- Formulaire gestion visible uniquement en ADMIN ou PROPRIÉTAIRE -->