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:
@@ -163,7 +163,10 @@ public class PhotoController {
|
|||||||
|
|
||||||
model.addAttribute("partages",
|
model.addAttribute("partages",
|
||||||
partageService.getPartagesForPhoto(id));
|
partageService.getPartagesForPhoto(id));
|
||||||
|
boolean isOwner = auth != null &&
|
||||||
|
photo.getProprietaire() != null &&
|
||||||
|
auth.getName().equals(photo.getProprietaire().getEmail());
|
||||||
|
model.addAttribute("isOwner", isOwner);
|
||||||
return "photo-detail";
|
return "photo-detail";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,6 +233,21 @@ public class PhotoController {
|
|||||||
return ResponseEntity.ok().contentType(MediaType.IMAGE_JPEG).body(r);
|
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";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -44,6 +44,8 @@ public class Album {
|
|||||||
private Set<Partage> partages = new HashSet<>();
|
private Set<Partage> partages = new HashSet<>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public enum Visibilite {
|
public enum Visibilite {
|
||||||
PRIVATE,
|
PRIVATE,
|
||||||
SHARED,
|
SHARED,
|
||||||
|
|||||||
@@ -35,6 +35,9 @@ public class Photo {
|
|||||||
@OneToMany(mappedBy = "photo", cascade = CascadeType.ALL, orphanRemoval = true)
|
@OneToMany(mappedBy = "photo", cascade = CascadeType.ALL, orphanRemoval = true)
|
||||||
private Set<Partage> partages = new HashSet<>();
|
private Set<Partage> partages = new HashSet<>();
|
||||||
|
|
||||||
|
@OneToMany(mappedBy = "photo", cascade = CascadeType.ALL, orphanRemoval = true)
|
||||||
|
private Set<Commentaire> commentaires = new HashSet<>();
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
private String uuidThumbnail;
|
private String uuidThumbnail;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ public interface PhotoService {
|
|||||||
Page<PhotoDTO> listSharedWith(String email, int page, int size);
|
Page<PhotoDTO> listSharedWith(String email, int page, int size);
|
||||||
Page<PhotoDTO> listSharedPhotos(String email, int page, int size);
|
Page<PhotoDTO> listSharedPhotos(String email, int page, int size);
|
||||||
List<PhotoDTO> listAllPhotosOfUser(String email);
|
List<PhotoDTO> listAllPhotosOfUser(String email);
|
||||||
|
void deletePhoto(Long id);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
package local.epul4a.fotosharing.service.impl;
|
package local.epul4a.fotosharing.service.impl;
|
||||||
|
|
||||||
|
import jakarta.transaction.Transactional;
|
||||||
import local.epul4a.fotosharing.dto.PhotoDTO;
|
import local.epul4a.fotosharing.dto.PhotoDTO;
|
||||||
import local.epul4a.fotosharing.mapper.PhotoMapper;
|
import local.epul4a.fotosharing.mapper.PhotoMapper;
|
||||||
|
import local.epul4a.fotosharing.model.Album;
|
||||||
import local.epul4a.fotosharing.model.Partage;
|
import local.epul4a.fotosharing.model.Partage;
|
||||||
import local.epul4a.fotosharing.model.Photo;
|
import local.epul4a.fotosharing.model.Photo;
|
||||||
import local.epul4a.fotosharing.model.Utilisateur;
|
import local.epul4a.fotosharing.model.Utilisateur;
|
||||||
@@ -185,4 +187,28 @@ public class PhotoServiceImpl implements PhotoService {
|
|||||||
.toList();
|
.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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -29,6 +29,17 @@
|
|||||||
<li><strong>Visibilité :</strong> <span th:text="${photo.visibilite}"></span></li>
|
<li><strong>Visibilité :</strong> <span th:text="${photo.visibilite}"></span></li>
|
||||||
<li><strong>Propriétaire :</strong> <span th:text="${photo.proprietaire.email}"></span></li>
|
<li><strong>Propriétaire :</strong> <span th:text="${photo.proprietaire.email}"></span></li>
|
||||||
</ul>
|
</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 -->
|
<!-- Partage de la photo -->
|
||||||
<!-- Formulaire gestion visible uniquement en ADMIN ou PROPRIÉTAIRE -->
|
<!-- Formulaire gestion visible uniquement en ADMIN ou PROPRIÉTAIRE -->
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -29,6 +29,17 @@
|
|||||||
<li><strong>Visibilité :</strong> <span th:text="${photo.visibilite}"></span></li>
|
<li><strong>Visibilité :</strong> <span th:text="${photo.visibilite}"></span></li>
|
||||||
<li><strong>Propriétaire :</strong> <span th:text="${photo.proprietaire.email}"></span></li>
|
<li><strong>Propriétaire :</strong> <span th:text="${photo.proprietaire.email}"></span></li>
|
||||||
</ul>
|
</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 -->
|
<!-- Partage de la photo -->
|
||||||
<!-- Formulaire gestion visible uniquement en ADMIN ou PROPRIÉTAIRE -->
|
<!-- Formulaire gestion visible uniquement en ADMIN ou PROPRIÉTAIRE -->
|
||||||
|
|||||||
Reference in New Issue
Block a user