FEAT : ajout partage simple
This commit is contained in:
@@ -1,8 +1,11 @@
|
||||
package local.epul4a.fotosharing.controller;
|
||||
|
||||
import local.epul4a.fotosharing.model.Partage;
|
||||
import local.epul4a.fotosharing.model.Photo;
|
||||
import local.epul4a.fotosharing.model.Utilisateur;
|
||||
import local.epul4a.fotosharing.repository.PartageRepository;
|
||||
import local.epul4a.fotosharing.repository.PhotoRepository;
|
||||
import local.epul4a.fotosharing.repository.UtilisateurRepository;
|
||||
import local.epul4a.fotosharing.security.CustomUserDetails;
|
||||
import local.epul4a.fotosharing.service.CommentaireService;
|
||||
import local.epul4a.fotosharing.service.PhotoService;
|
||||
@@ -11,6 +14,7 @@ import org.springframework.core.io.PathResource;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||
import org.springframework.stereotype.Controller;
|
||||
@@ -20,6 +24,7 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
@Controller
|
||||
public class PhotoController {
|
||||
@@ -27,11 +32,15 @@ public class PhotoController {
|
||||
private final PhotoService photoService;
|
||||
private final PhotoRepository photoRepository;
|
||||
private final CommentaireService commentaireService;
|
||||
private final UtilisateurRepository utilisateurRepository;
|
||||
private final PartageRepository partageRepository;
|
||||
|
||||
public PhotoController(PhotoService photoService, PhotoRepository photoRepository, CommentaireService commentaireService) {
|
||||
public PhotoController(PhotoService photoService, PhotoRepository photoRepository, CommentaireService commentaireService, UtilisateurRepository utilisateurRepository, PartageRepository partageRepository) {
|
||||
this.photoService = photoService;
|
||||
this.photoRepository = photoRepository;
|
||||
this.commentaireService = commentaireService;
|
||||
this.utilisateurRepository = utilisateurRepository;
|
||||
this.partageRepository = partageRepository;
|
||||
}
|
||||
|
||||
@GetMapping("/upload")
|
||||
@@ -84,7 +93,13 @@ public class PhotoController {
|
||||
@GetMapping("/mes-photos")
|
||||
public String mesPhotos(Model model, Authentication authentication) {
|
||||
String email = authentication.getName();
|
||||
model.addAttribute("photos", photoService.listByOwner(email));
|
||||
// photos que je possède
|
||||
List<Photo> mesPhotos = photoService.listByOwner(email);
|
||||
// photos partagées avec moi
|
||||
List<Photo> photosPartagees = photoService.listSharedWith(email);
|
||||
model.addAttribute("mesPhotos", mesPhotos);
|
||||
model.addAttribute("photosPartagees", photosPartagees);
|
||||
|
||||
return "mes-photos";
|
||||
}
|
||||
|
||||
@@ -95,6 +110,7 @@ public class PhotoController {
|
||||
}
|
||||
|
||||
@GetMapping("/photo/{id}")
|
||||
@PreAuthorize("@securityService.canAccessPhoto(authentication, #id)")
|
||||
public String viewPhoto(@PathVariable Long id,
|
||||
Model model,
|
||||
Authentication auth) {
|
||||
@@ -126,5 +142,30 @@ public class PhotoController {
|
||||
return "redirect:/photo/" + id;
|
||||
}
|
||||
|
||||
@PostMapping("/photo/{id}/share")
|
||||
@PreAuthorize("@securityService.canAccessPhoto(authentication, #id)")
|
||||
public String share(@PathVariable Long id,
|
||||
@RequestParam String email,
|
||||
Authentication auth) {
|
||||
// Vérifier que c'est le propriétaire
|
||||
Photo photo = photoRepository.findById(id).orElse(null);
|
||||
if (photo == null) return "redirect:/galerie";
|
||||
if (!photo.getProprietaire().getEmail().equals(auth.getName())) {
|
||||
return "redirect:/photo/" + id + "?error=notowner";
|
||||
}
|
||||
// Trouver utilisateur
|
||||
Utilisateur user = utilisateurRepository.findByEmail(email).orElse(null);
|
||||
if (user == null) {
|
||||
return "redirect:/photo/" + id + "?error=usernotfound";
|
||||
}
|
||||
// Ajouter partage
|
||||
Partage p = new Partage();
|
||||
p.setPhoto(photo);
|
||||
p.setUtilisateur(user);
|
||||
partageRepository.save(p);
|
||||
return "redirect:/photo/" + id + "?shared=ok";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package local.epul4a.fotosharing.repository;
|
||||
|
||||
import local.epul4a.fotosharing.model.Partage;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface PartageRepository extends JpaRepository<Partage, Long> {
|
||||
// liste des partages pour une photo
|
||||
List<Partage> findByPhoto_Id(Long photoId);
|
||||
// vérifier si un utilisateur a accès partagé
|
||||
boolean existsByPhoto_IdAndUtilisateur_Email(Long photoId, String email);
|
||||
List<Partage> findByUtilisateur_Email(String email);
|
||||
|
||||
}
|
||||
@@ -1,29 +1,47 @@
|
||||
package local.epul4a.fotosharing.security;
|
||||
|
||||
import local.epul4a.fotosharing.model.Photo;
|
||||
import local.epul4a.fotosharing.repository.PartageRepository;
|
||||
import local.epul4a.fotosharing.repository.PhotoRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.naming.ldap.PagedResultsControl;
|
||||
import java.util.Optional;
|
||||
import org.springframework.security.core.Authentication;
|
||||
|
||||
|
||||
@Service("securityService")
|
||||
public class SecurityService {
|
||||
|
||||
private final PhotoRepository photoRepository;
|
||||
private final PartageRepository partageRepository;
|
||||
|
||||
public SecurityService(PhotoRepository photoRepository) {
|
||||
public SecurityService(PhotoRepository photoRepository, PartageRepository partageRepository) {
|
||||
this.photoRepository = photoRepository;
|
||||
this.partageRepository = partageRepository;
|
||||
}
|
||||
|
||||
public boolean canAccessPhoto(org.springframework.security.core.Authentication authentication, Long photoId) {
|
||||
if (authentication == null || !authentication.isAuthenticated()) return false;
|
||||
String username = authentication.getName(); // email
|
||||
Optional<Photo> p = photoRepository.findById(photoId);
|
||||
if (p.isEmpty()) return false;
|
||||
Photo photo = p.get();
|
||||
if (photo.getVisibilite() == Photo.Visibilite.PUBLIC) return true;
|
||||
if (photo.getProprietaire() != null && photo.getProprietaire().getEmail().equals(username)) return true;
|
||||
// TODO: vérifier table partage
|
||||
public boolean canAccessPhoto(Authentication authentication, Long photoId) {
|
||||
Photo photo = photoRepository.findById(photoId).orElse(null);
|
||||
if (photo == null) return false;
|
||||
// PUBLIC → accès total
|
||||
if (photo.getVisibilite() == Photo.Visibilite.PUBLIC) {
|
||||
return true;
|
||||
}
|
||||
// Pas connecté → rejeter tout sauf PUBLIC
|
||||
if (authentication == null || !authentication.isAuthenticated()) {
|
||||
return false;
|
||||
}
|
||||
String email = authentication.getName();
|
||||
// Propriétaire → OK
|
||||
if (photo.getProprietaire().getEmail().equals(email)) {
|
||||
return true;
|
||||
}
|
||||
// SHARED → vérifier dans la table PARTAGE
|
||||
if (photo.getVisibilite() == Photo.Visibilite.SHARED) {
|
||||
return partageRepository.existsByPhoto_IdAndUtilisateur_Email(photoId, email);
|
||||
}
|
||||
// PRIVATE par défaut → refus
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,5 +11,7 @@ public interface PhotoService {
|
||||
Path loadAsPath(String uuidFile);
|
||||
List<Photo> listByOwner(String email);
|
||||
List<Photo> listPublicPhotos();
|
||||
List<Photo> listSharedWith(String email);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package local.epul4a.fotosharing.service.impl;
|
||||
|
||||
import local.epul4a.fotosharing.model.Partage;
|
||||
import local.epul4a.fotosharing.model.Photo;
|
||||
import local.epul4a.fotosharing.model.Utilisateur;
|
||||
import local.epul4a.fotosharing.repository.PartageRepository;
|
||||
import local.epul4a.fotosharing.repository.PhotoRepository;
|
||||
import local.epul4a.fotosharing.repository.UtilisateurRepository;
|
||||
import local.epul4a.fotosharing.service.PhotoService;
|
||||
@@ -24,10 +26,12 @@ public class PhotoServiceImpl implements PhotoService {
|
||||
|
||||
private final PhotoRepository photoRepository;
|
||||
private final UtilisateurRepository utilisateurRepository;
|
||||
private final PartageRepository partageRepository;
|
||||
|
||||
public PhotoServiceImpl(PhotoRepository photoRepository, UtilisateurRepository utilisateurRepository) {
|
||||
public PhotoServiceImpl(PhotoRepository photoRepository, UtilisateurRepository utilisateurRepository, PartageRepository partageRepository) {
|
||||
this.photoRepository = photoRepository;
|
||||
this.utilisateurRepository = utilisateurRepository;
|
||||
this.partageRepository = partageRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -69,4 +73,14 @@ public class PhotoServiceImpl implements PhotoService {
|
||||
public List<Photo> listPublicPhotos() {
|
||||
return photoRepository.findByVisibilite(Photo.Visibilite.PUBLIC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Photo> listSharedWith(String email) {
|
||||
List<Partage> partages = partageRepository.findByUtilisateur_Email(email);
|
||||
|
||||
return partages.stream()
|
||||
.map(Partage::getPhoto)
|
||||
.toList();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,23 +5,34 @@
|
||||
<title>Mes photos</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Mes photos</h1>
|
||||
|
||||
<h2>Mes photos</h2>
|
||||
<p><a th:href="@{/upload}">Uploader une photo</a></p>
|
||||
<p><a th:href="@{/}">Retour accueil</a></p>
|
||||
|
||||
<div th:if="${#lists.isEmpty(photos)}">
|
||||
<div th:if="${#lists.isEmpty(mesPhotos)}">
|
||||
<p>Vous n'avez pas encore de photos.</p>
|
||||
</div>
|
||||
|
||||
<ul th:if="${!#lists.isEmpty(photos)}">
|
||||
<li th:each="p : ${photos}">
|
||||
<span th:text="${p.nomFichierOriginal}">Nom du fichier</span>
|
||||
<ul>
|
||||
<li th:each="p : ${mesPhotos}">
|
||||
<span th:text="${p.nomFichierOriginal}"></span>
|
||||
—
|
||||
<a th:href="@{'/photo/' + ${p.id}}">Voir</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2>Photos partagées avec moi</h2>
|
||||
<div th:if="${#lists.isEmpty(photosPartagees)}">
|
||||
<p>Aucune photo partagée.</p>
|
||||
</div>
|
||||
<ul th:if="${!#lists.isEmpty(photosPartagees)}">
|
||||
<li th:each="p : ${photosPartagees}">
|
||||
<span th:text="${p.nomFichierOriginal}"></span>
|
||||
<span style="color: green; font-weight: bold;">[SHARED]</span>
|
||||
—
|
||||
<a th:href="@{'/photo/' + ${p.id}}">Voir</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p><a th:href="@{/galerie}">Galerie publique</a></p>
|
||||
|
||||
</body>
|
||||
|
||||
@@ -29,6 +29,20 @@
|
||||
<li><strong>Propriétaire :</strong> <span th:text="${photo.proprietaire.email}"></span></li>
|
||||
</ul>
|
||||
|
||||
<!-- Partage de la photo -->
|
||||
<h2>Partager la photo</h2>
|
||||
<div th:if="${currentUser == photo.proprietaire.email}">
|
||||
<form th:action="@{'/photo/' + ${photo.id} + '/share'}" method="post">
|
||||
<label>Email de l'utilisateur :</label>
|
||||
<input type="email" name="email" required />
|
||||
<button type="submit">Partager</button>
|
||||
</form>
|
||||
</div>
|
||||
<div th:if="${currentUser != photo.proprietaire.email}">
|
||||
<em>Seul le propriétaire peut partager cette photo.</em>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Commentaires -->
|
||||
<h2>Commentaires</h2>
|
||||
<div th:if="${#lists.isEmpty(commentaires)}">
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -5,23 +5,34 @@
|
||||
<title>Mes photos</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Mes photos</h1>
|
||||
|
||||
<h2>Mes photos</h2>
|
||||
<p><a th:href="@{/upload}">Uploader une photo</a></p>
|
||||
<p><a th:href="@{/}">Retour accueil</a></p>
|
||||
|
||||
<div th:if="${#lists.isEmpty(photos)}">
|
||||
<div th:if="${#lists.isEmpty(mesPhotos)}">
|
||||
<p>Vous n'avez pas encore de photos.</p>
|
||||
</div>
|
||||
|
||||
<ul th:if="${!#lists.isEmpty(photos)}">
|
||||
<li th:each="p : ${photos}">
|
||||
<span th:text="${p.nomFichierOriginal}">Nom du fichier</span>
|
||||
<ul>
|
||||
<li th:each="p : ${mesPhotos}">
|
||||
<span th:text="${p.nomFichierOriginal}"></span>
|
||||
—
|
||||
<a th:href="@{'/photo/' + ${p.id}}">Voir</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2>Photos partagées avec moi</h2>
|
||||
<div th:if="${#lists.isEmpty(photosPartagees)}">
|
||||
<p>Aucune photo partagée.</p>
|
||||
</div>
|
||||
<ul th:if="${!#lists.isEmpty(photosPartagees)}">
|
||||
<li th:each="p : ${photosPartagees}">
|
||||
<span th:text="${p.nomFichierOriginal}"></span>
|
||||
<span style="color: green; font-weight: bold;">[SHARED]</span>
|
||||
—
|
||||
<a th:href="@{'/photo/' + ${p.id}}">Voir</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p><a th:href="@{/galerie}">Galerie publique</a></p>
|
||||
|
||||
</body>
|
||||
|
||||
@@ -29,6 +29,20 @@
|
||||
<li><strong>Propriétaire :</strong> <span th:text="${photo.proprietaire.email}"></span></li>
|
||||
</ul>
|
||||
|
||||
<!-- Partage de la photo -->
|
||||
<h2>Partager la photo</h2>
|
||||
<div th:if="${currentUser == photo.proprietaire.email}">
|
||||
<form th:action="@{'/photo/' + ${photo.id} + '/share'}" method="post">
|
||||
<label>Email de l'utilisateur :</label>
|
||||
<input type="email" name="email" required />
|
||||
<button type="submit">Partager</button>
|
||||
</form>
|
||||
</div>
|
||||
<div th:if="${currentUser != photo.proprietaire.email}">
|
||||
<em>Seul le propriétaire peut partager cette photo.</em>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Commentaires -->
|
||||
<h2>Commentaires</h2>
|
||||
<div th:if="${#lists.isEmpty(commentaires)}">
|
||||
|
||||
Reference in New Issue
Block a user