CORRECTION BUG & AMELIORATION : Gestion de la visibilite et des partages de photos (ACL)

This commit is contained in:
2025-12-03 09:13:37 +01:00
parent 6c3ea128af
commit b144a44a0a
10 changed files with 108 additions and 40 deletions

View File

@@ -18,6 +18,9 @@ import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
@Controller @Controller
public class PhotoController { public class PhotoController {
@@ -181,8 +184,13 @@ public class PhotoController {
@RequestParam String permission, @RequestParam String permission,
Authentication auth) { Authentication auth) {
partageService.share(id, email, permission, auth.getName()); try {
return "redirect:/photo/" + id + "?shared=ok"; partageService.share(id, email, permission, auth.getName());
return "redirect:/photo/" + id + "?shared=ok";
} catch (RuntimeException ex) {
return "redirect:/photo/" + id + "?error=" + URLEncoder.encode(ex.getMessage(), StandardCharsets.UTF_8);
}
} }
@@ -193,4 +201,18 @@ public class PhotoController {
partageService.unshare(id, email); partageService.unshare(id, email);
return "redirect:/photo/" + id; return "redirect:/photo/" + id;
} }
/* ========================== MAJ MODE PARTAGE ========================== */
@PostMapping("/photo/{id}/share/update")
@PreAuthorize("@securityService.canAccessPhoto(authentication, #id)")
public String updateShare(
@PathVariable Long id,
@RequestParam String email,
@RequestParam String permission,
Authentication auth
) {
partageService.updatePermission(id, email, permission, auth.getName());
return "redirect:/photo/" + id;
}
} }

View File

@@ -4,17 +4,17 @@ import local.epul4a.fotosharing.dto.PartageDTO;
import local.epul4a.fotosharing.model.Partage; import local.epul4a.fotosharing.model.Partage;
public class PartageMapper { public class PartageMapper {
public static PartageDTO toDTO(Partage p) { public static PartageDTO toDTO(Partage p) {
if (p == null) return null; if (p == null) return null;
PartageDTO dto = new PartageDTO(); PartageDTO dto = new PartageDTO();
dto.setId(p.getId()); dto.setId(p.getId());
dto.setPermission(p.getPermission().name());
dto.setUtilisateur(UtilisateurMapper.toDTO(p.getUtilisateur())); dto.setUtilisateur(UtilisateurMapper.toDTO(p.getUtilisateur()));
dto.setPhoto(PhotoMapper.toDTO(p.getPhoto())); dto.setPhoto(PhotoMapper.toDTO(p.getPhoto()));
dto.setPermission(p.getPermission().name());
return dto; return dto;
} }
} }

View File

@@ -13,5 +13,5 @@ public interface PartageService {
boolean canView(Long photoId, String email); boolean canView(Long photoId, String email);
boolean canComment(Long photoId, String email); boolean canComment(Long photoId, String email);
boolean canAdmin(Long photoId, String email); boolean canAdmin(Long photoId, String email);
void updatePermission(Long photoId, String targetEmail, String newPermission, String ownerEmail);
} }

View File

@@ -40,29 +40,25 @@ public class PartageServiceImpl implements PartageService {
@Override @Override
public void share(Long photoId, String targetEmail, String permissionStr, String ownerEmail) { public void share(Long photoId, String targetEmail, String permissionStr, String ownerEmail) {
Photo photo = photoRepository.findById(photoId) Photo photo = photoRepository.findById(photoId)
.orElseThrow(() -> new RuntimeException("Photo introuvable")); .orElseThrow(() -> new RuntimeException("Photo introuvable"));
if (!photo.getProprietaire().getEmail().equals(ownerEmail)) if (!photo.getProprietaire().getEmail().equals(ownerEmail))
throw new RuntimeException("Vous n'êtes pas propriétaire"); throw new RuntimeException("Vous n'êtes pas propriétaire");
Utilisateur target = utilisateurRepository.findByEmail(targetEmail) Utilisateur target = utilisateurRepository.findByEmail(targetEmail)
.orElseThrow(() -> new RuntimeException("Utilisateur introuvable")); .orElseThrow(() -> new RuntimeException("Utilisateur introuvable"));
// Nouveauté ici : renvoyer un message explicite
if (partageRepository.existsByPhoto_IdAndUtilisateur_Email(photoId, targetEmail)) if (partageRepository.existsByPhoto_IdAndUtilisateur_Email(photoId, targetEmail)) {
return; throw new RuntimeException("Cet utilisateur a déjà accès à cette photo");
}
Partage.Permission permission = Partage.Permission.valueOf(permissionStr); Partage.Permission permission = Partage.Permission.valueOf(permissionStr);
Partage partage = new Partage(); Partage partage = new Partage();
partage.setPhoto(photo); partage.setPhoto(photo);
partage.setUtilisateur(target); partage.setUtilisateur(target);
partage.setPermission(permission); partage.setPermission(permission);
partageRepository.save(partage); partageRepository.save(partage);
} }
@Override @Override
public void unshare(Long photoId, String targetEmail) { public void unshare(Long photoId, String targetEmail) {
@@ -121,4 +117,28 @@ public class PartageServiceImpl implements PartageService {
return partage.getPermission() == Partage.Permission.ADMIN; return partage.getPermission() == Partage.Permission.ADMIN;
} }
@Override
public void updatePermission(Long photoId, String targetEmail, String newPermission, String requesterEmail) {
Photo photo = photoRepository.findById(photoId)
.orElseThrow(() -> new RuntimeException("Photo introuvable"));
//Vérifier si requester = propriétaire
if (!photo.getProprietaire().getEmail().equals(requesterEmail)) {
// Sinon, vérifier s'il a ADMIN
Partage requesterPartage = partageRepository
.findByPhoto_IdAndUtilisateur_Email(photoId, requesterEmail)
.orElse(null);
if (requesterPartage == null || requesterPartage.getPermission() != Partage.Permission.ADMIN) {
throw new RuntimeException("Vous navez pas les droits ADMIN pour modifier les permissions.");
}
}
// OK → modification des droits
Partage partage = partageRepository
.findByPhoto_IdAndUtilisateur_Email(photoId, targetEmail)
.orElseThrow(() -> new RuntimeException("Partage introuvable"));
Partage.Permission permission = Partage.Permission.valueOf(newPermission);
partage.setPermission(permission);
partageRepository.save(partage);
}
} }

View File

@@ -31,21 +31,34 @@
</ul> </ul>
<!-- Partage de la photo --> <!-- Partage de la photo -->
<h2>Partagée avec :</h2> <!-- Formulaire gestion visible uniquement en ADMIN ou PROPRIÉTAIRE -->
<ul>
<li th:each="p : ${partages}">
<span th:text="${p.utilisateur.email}"></span>
<span> - <b th:text="${p.permission}"></b></span>
<!-- ADMIN OU PROPRIÉTAIRE : peut retirer -->
<a th:if="${canAdmin}"
th:href="@{'/photo/' + ${photo.id} + '/unshare/' + ${p.utilisateur.email}}"
style="color:red; margin-left:10px;">Retirer</a>
</li>
</ul>
<!-- Formulaire dajout visible uniquement en ADMIN ou PROPRIÉTAIRE -->
<div th:if="${canAdmin}"> <div th:if="${canAdmin}">
<h2>Partagée avec :</h2>
<ul>
<li th:each="p : ${partages}">
<span th:text="${p.utilisateur.email}"></span>
<!-- Formulaire modification permission -->
<form th:action="@{'/photo/' + ${photo.id} + '/share/update'}" method="post" style="display:inline;">
<input type="hidden" name="email" th:value="${p.utilisateur.email}" />
<select name="permission">
<option value="READ" th:selected="${p.permission == 'READ'}">Lecture</option>
<option value="COMMENT" th:selected="${p.permission == 'COMMENT'}">Commentaire</option>
<option value="ADMIN" th:selected="${p.permission == 'ADMIN'}">Administration</option>
</select>
<button type="submit">Modifier</button>
</form>
<!-- Unshare -->
<a th:href="@{'/photo/' + ${photo.id} + '/unshare/' + ${p.utilisateur.email}}"
style="color:red; margin-left:10px;">Retirer</a>
</li>
</ul>
<h3>Partager la photo</h3> <h3>Partager la photo</h3>
<div th:if="${param.error}" style="color:red; font-weight:bold;">
<span th:text="${param.error}"></span>
</div>
<div th:if="${param.shared}" style="color:green; font-weight:bold;">
Partage effectué avec succès !
</div>
<form th:action="@{'/photo/' + ${photo.id} + '/share'}" method="post"> <form th:action="@{'/photo/' + ${photo.id} + '/share'}" method="post">
<label>Email de l'utilisateur :</label> <label>Email de l'utilisateur :</label>
<input type="email" name="email" required /> <input type="email" name="email" required />

View File

@@ -31,21 +31,34 @@
</ul> </ul>
<!-- Partage de la photo --> <!-- Partage de la photo -->
<h2>Partagée avec :</h2> <!-- Formulaire gestion visible uniquement en ADMIN ou PROPRIÉTAIRE -->
<ul>
<li th:each="p : ${partages}">
<span th:text="${p.utilisateur.email}"></span>
<span> - <b th:text="${p.permission}"></b></span>
<!-- ADMIN OU PROPRIÉTAIRE : peut retirer -->
<a th:if="${canAdmin}"
th:href="@{'/photo/' + ${photo.id} + '/unshare/' + ${p.utilisateur.email}}"
style="color:red; margin-left:10px;">Retirer</a>
</li>
</ul>
<!-- Formulaire dajout visible uniquement en ADMIN ou PROPRIÉTAIRE -->
<div th:if="${canAdmin}"> <div th:if="${canAdmin}">
<h2>Partagée avec :</h2>
<ul>
<li th:each="p : ${partages}">
<span th:text="${p.utilisateur.email}"></span>
<!-- Formulaire modification permission -->
<form th:action="@{'/photo/' + ${photo.id} + '/share/update'}" method="post" style="display:inline;">
<input type="hidden" name="email" th:value="${p.utilisateur.email}" />
<select name="permission">
<option value="READ" th:selected="${p.permission == 'READ'}">Lecture</option>
<option value="COMMENT" th:selected="${p.permission == 'COMMENT'}">Commentaire</option>
<option value="ADMIN" th:selected="${p.permission == 'ADMIN'}">Administration</option>
</select>
<button type="submit">Modifier</button>
</form>
<!-- Unshare -->
<a th:href="@{'/photo/' + ${photo.id} + '/unshare/' + ${p.utilisateur.email}}"
style="color:red; margin-left:10px;">Retirer</a>
</li>
</ul>
<h3>Partager la photo</h3> <h3>Partager la photo</h3>
<div th:if="${param.error}" style="color:red; font-weight:bold;">
<span th:text="${param.error}"></span>
</div>
<div th:if="${param.shared}" style="color:green; font-weight:bold;">
Partage effectué avec succès !
</div>
<form th:action="@{'/photo/' + ${photo.id} + '/share'}" method="post"> <form th:action="@{'/photo/' + ${photo.id} + '/share'}" method="post">
<label>Email de l'utilisateur :</label> <label>Email de l'utilisateur :</label>
<input type="email" name="email" required /> <input type="email" name="email" required />