refactor pour intégrer l'architecture 3-tiers
This commit is contained in:
@@ -1,49 +1,46 @@
|
||||
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.dto.CommentaireDTO;
|
||||
import local.epul4a.fotosharing.dto.PartageDTO;
|
||||
import local.epul4a.fotosharing.dto.PhotoDTO;
|
||||
import local.epul4a.fotosharing.service.CommentaireService;
|
||||
import local.epul4a.fotosharing.service.PartageService;
|
||||
import local.epul4a.fotosharing.service.PhotoService;
|
||||
import local.epul4a.fotosharing.service.UtilisateurService;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.PathResource;
|
||||
import org.springframework.data.domain.Page;
|
||||
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;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
@Controller
|
||||
public class PhotoController {
|
||||
|
||||
private final PhotoService photoService;
|
||||
private final PhotoRepository photoRepository;
|
||||
private final CommentaireService commentaireService;
|
||||
private final UtilisateurRepository utilisateurRepository;
|
||||
private final PartageRepository partageRepository;
|
||||
private final PartageService partageService;
|
||||
private final UtilisateurService utilisateurService;
|
||||
|
||||
public PhotoController(PhotoService photoService, PhotoRepository photoRepository, CommentaireService commentaireService, UtilisateurRepository utilisateurRepository, PartageRepository partageRepository) {
|
||||
public PhotoController(
|
||||
PhotoService photoService,
|
||||
CommentaireService commentaireService,
|
||||
PartageService partageService,
|
||||
UtilisateurService utilisateurService
|
||||
) {
|
||||
this.photoService = photoService;
|
||||
this.photoRepository = photoRepository;
|
||||
this.commentaireService = commentaireService;
|
||||
this.utilisateurRepository = utilisateurRepository;
|
||||
this.partageRepository = partageRepository;
|
||||
this.partageService = partageService;
|
||||
this.utilisateurService = utilisateurService;
|
||||
}
|
||||
|
||||
|
||||
/* ========================== UPLOAD ========================== */
|
||||
|
||||
@GetMapping("/upload")
|
||||
public String uploadForm() {
|
||||
return "upload";
|
||||
@@ -52,147 +49,142 @@ public class PhotoController {
|
||||
@PostMapping("/upload")
|
||||
public String doUpload(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "visibilite", defaultValue = "PRIVATE") String visibilite,
|
||||
Authentication authentication,
|
||||
Authentication auth,
|
||||
Model model) {
|
||||
try {
|
||||
String email = authentication.getName(); // l'email de l'utilisateur connecté
|
||||
Photo p = photoService.store(file, visibilite, email);
|
||||
model.addAttribute("message", "Upload OK : " + p.getId());
|
||||
return "redirect:/";
|
||||
} catch (Exception e) {
|
||||
model.addAttribute("error", e.getMessage());
|
||||
photoService.store(file, visibilite, auth.getName());
|
||||
return "redirect:/mes-photos";
|
||||
} catch (Exception ex) {
|
||||
model.addAttribute("error", ex.getMessage());
|
||||
return "upload";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ========================== RAW IMAGE ========================== */
|
||||
|
||||
@GetMapping("/photo/{id}/raw")
|
||||
public ResponseEntity<Resource> rawPhoto(@PathVariable("id") Long id) {
|
||||
Photo photo = photoRepository.findById(id).orElse(null);
|
||||
if (photo == null) {
|
||||
public ResponseEntity<Resource> rawPhoto(@PathVariable Long id) {
|
||||
|
||||
PhotoDTO photo = photoService.getPhotoById(id);
|
||||
if (photo == null)
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
Path p = photoService.loadAsPath(photo.getUuidFichier());
|
||||
Resource r = new PathResource(p);
|
||||
|
||||
if (!r.exists()) {
|
||||
Resource r = photoService.loadAsResource(photo.getUuidFichier());
|
||||
if (!r.exists())
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
String contentType = "application/octet-stream";
|
||||
try {
|
||||
contentType = Files.probeContentType(p);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
|
||||
return ResponseEntity.ok()
|
||||
.contentType(MediaType.parseMediaType(contentType))
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION,
|
||||
"inline; filename=\"" + photo.getNomFichierOriginal() + "\"")
|
||||
.contentType(MediaType.IMAGE_JPEG) // simplifiable, ou détecté dans service
|
||||
.body(r);
|
||||
}
|
||||
|
||||
|
||||
/* ========================== MES PHOTOS ========================== */
|
||||
|
||||
@GetMapping("/mes-photos")
|
||||
public String mesPhotos(
|
||||
@RequestParam(name = "pagePrivees", defaultValue = "0") int pagePrivees,
|
||||
@RequestParam(name = "pagePubliques", defaultValue = "0") int pagePubliques,
|
||||
@RequestParam(name = "pagePartagees", defaultValue = "0") int pagePartagees,
|
||||
@RequestParam(name = "pageMesPartagees", defaultValue = "0") int pageMesPartagees,
|
||||
Model model,
|
||||
Authentication auth
|
||||
) {
|
||||
String email = auth.getName();
|
||||
// Chaque liste utilise sa propre pagination
|
||||
model.addAttribute("photosPrivees", photoService.listPrivatePhotos(email, pagePrivees, 12));
|
||||
model.addAttribute("photosPubliques", photoService.listPublicPhotos(email, pagePubliques, 12));
|
||||
model.addAttribute("photosPartagees", photoService.listSharedWith(email, pagePartagees, 12));
|
||||
model.addAttribute("mesPhotosPartagees", photoService.listSharedPhotos(email, pageMesPartagees, 12));
|
||||
@RequestParam(defaultValue = "0") int pagePrivees,
|
||||
@RequestParam(defaultValue = "0") int pagePubliques,
|
||||
@RequestParam(defaultValue = "0") int pagePartagees,
|
||||
@RequestParam(defaultValue = "0") int pageMesPartagees,
|
||||
Authentication auth, Model model) {
|
||||
|
||||
String email = auth.getName();
|
||||
|
||||
model.addAttribute("photosPrivees",
|
||||
photoService.listPrivatePhotos(email, pagePrivees, 12));
|
||||
|
||||
model.addAttribute("photosPubliques",
|
||||
photoService.listPublicPhotos(email, pagePubliques, 12));
|
||||
|
||||
model.addAttribute("photosPartagees",
|
||||
photoService.listSharedWith(email, pagePartagees, 12));
|
||||
|
||||
model.addAttribute("mesPhotosPartagees",
|
||||
photoService.listSharedPhotos(email, pageMesPartagees, 12));
|
||||
|
||||
// Ajouter les 3 index séparés
|
||||
model.addAttribute("pagePrivees", pagePrivees);
|
||||
model.addAttribute("pagePubliques", pagePubliques);
|
||||
model.addAttribute("pagePartagees", pagePartagees);
|
||||
model.addAttribute("pageMesPartagees", pageMesPartagees);
|
||||
|
||||
return "mes-photos";
|
||||
}
|
||||
|
||||
|
||||
/* ========================== GALERIE ========================== */
|
||||
|
||||
@GetMapping("/galerie")
|
||||
public String galerie(@RequestParam(defaultValue = "0") int page, Model model) {
|
||||
Page<Photo> photosPage = photoService.listPublic(page, 12);
|
||||
|
||||
Page<PhotoDTO> photosPage = photoService.listPublic(page, 12);
|
||||
|
||||
model.addAttribute("photosPage", photosPage);
|
||||
model.addAttribute("currentPage", page);
|
||||
|
||||
return "galerie";
|
||||
}
|
||||
|
||||
|
||||
/* ========================== DETAIL PHOTO ========================== */
|
||||
|
||||
@GetMapping("/photo/{id}")
|
||||
@PreAuthorize("@securityService.canAccessPhoto(authentication, #id)")
|
||||
public String viewPhoto(@PathVariable Long id,
|
||||
@RequestParam(defaultValue = "0") int page,
|
||||
Model model,
|
||||
Authentication auth) {
|
||||
Photo photo = photoRepository.findById(id).orElse(null);
|
||||
if (photo == null) {
|
||||
Authentication auth,
|
||||
Model model) {
|
||||
|
||||
PhotoDTO photo = photoService.getPhotoById(id);
|
||||
if (photo == null)
|
||||
return "redirect:/galerie";
|
||||
}
|
||||
|
||||
model.addAttribute("photo", photo);
|
||||
// Pagination des commentaires
|
||||
model.addAttribute("commentairesPage",
|
||||
commentaireService.listByPhoto(id, page, 10));
|
||||
|
||||
Page<CommentaireDTO> commentaires =
|
||||
commentaireService.listByPhoto(id, page, 10);
|
||||
model.addAttribute("commentairesPage", commentaires);
|
||||
model.addAttribute("currentPage", page);
|
||||
// utilisateur connecté (peut être null)
|
||||
|
||||
String currentUser = (auth != null ? auth.getName() : null);
|
||||
model.addAttribute("currentUser", currentUser);
|
||||
// Liste des partages
|
||||
List<Partage> partages = partageRepository.findByPhoto_Id(id);
|
||||
model.addAttribute("partages", partages);
|
||||
|
||||
model.addAttribute("partages",
|
||||
partageService.getPartagesForPhoto(id));
|
||||
|
||||
return "photo-detail";
|
||||
}
|
||||
|
||||
/* ========================== COMMENTAIRES ========================== */
|
||||
|
||||
@PostMapping("/photo/{id}/comment")
|
||||
public String addComment(@PathVariable Long id,
|
||||
@RequestParam String contenu,
|
||||
Authentication auth) {
|
||||
if (auth == null) {
|
||||
return "redirect:/login";
|
||||
}
|
||||
String email = auth.getName();
|
||||
commentaireService.addComment(id, email, contenu);
|
||||
|
||||
commentaireService.addComment(id, auth.getName(), contenu);
|
||||
return "redirect:/photo/" + id;
|
||||
}
|
||||
|
||||
|
||||
/* ========================== PARTAGE PHOTO ========================== */
|
||||
@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);
|
||||
public String sharePhoto(@PathVariable Long id,
|
||||
@RequestParam String email,
|
||||
@RequestParam String permission,
|
||||
Authentication auth) {
|
||||
|
||||
partageService.share(id, email, permission, auth.getName());
|
||||
return "redirect:/photo/" + id + "?shared=ok";
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/photo/{id}/unshare/{email}")
|
||||
public String unshare(@PathVariable Long id, @PathVariable String email) {
|
||||
photoService.unshare(id, email);
|
||||
|
||||
partageService.unshare(id, email);
|
||||
return "redirect:/photo/" + id;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package local.epul4a.fotosharing.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class CommentaireDTO {
|
||||
private Long id;
|
||||
private String contenu;
|
||||
private LocalDateTime dateCommentaire;
|
||||
private UtilisateurDTO auteur;
|
||||
}
|
||||
13
src/main/java/local/epul4a/fotosharing/dto/PartageDTO.java
Normal file
13
src/main/java/local/epul4a/fotosharing/dto/PartageDTO.java
Normal file
@@ -0,0 +1,13 @@
|
||||
package local.epul4a.fotosharing.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class PartageDTO {
|
||||
private Long id;
|
||||
private UtilisateurDTO utilisateur;
|
||||
private String permission; // READ / COMMENT / ADMIN
|
||||
private PhotoDTO photo;
|
||||
}
|
||||
19
src/main/java/local/epul4a/fotosharing/dto/PhotoDTO.java
Normal file
19
src/main/java/local/epul4a/fotosharing/dto/PhotoDTO.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package local.epul4a.fotosharing.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class PhotoDTO {
|
||||
|
||||
private Long id;
|
||||
private String nomFichierOriginal;
|
||||
private String uuidFichier;
|
||||
private LocalDateTime dateUpload;
|
||||
private String visibilite;
|
||||
private UtilisateurDTO proprietaire;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package local.epul4a.fotosharing.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class UtilisateurDTO {
|
||||
|
||||
private Long id;
|
||||
private String email;
|
||||
private String nom;
|
||||
private String prenom;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package local.epul4a.fotosharing.mapper;
|
||||
|
||||
import local.epul4a.fotosharing.dto.CommentaireDTO;
|
||||
import local.epul4a.fotosharing.model.Commentaire;
|
||||
|
||||
public class CommentaireMapper {
|
||||
|
||||
public static CommentaireDTO toDTO(Commentaire c) {
|
||||
if (c == null) return null;
|
||||
CommentaireDTO dto = new CommentaireDTO();
|
||||
dto.setId(c.getId());
|
||||
dto.setContenu(c.getContenu());
|
||||
dto.setDateCommentaire(c.getDateCommentaire());
|
||||
// Auteur via mapper dédié
|
||||
dto.setAuteur(UtilisateurMapper.toDTO(c.getAuteur()));
|
||||
return dto;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package local.epul4a.fotosharing.mapper;
|
||||
|
||||
import local.epul4a.fotosharing.dto.PartageDTO;
|
||||
import local.epul4a.fotosharing.model.Partage;
|
||||
|
||||
public class PartageMapper {
|
||||
|
||||
public static PartageDTO toDTO(Partage p) {
|
||||
if (p == null) return null;
|
||||
|
||||
PartageDTO dto = new PartageDTO();
|
||||
dto.setId(p.getId());
|
||||
dto.setUtilisateur(UtilisateurMapper.toDTO(p.getUtilisateur()));
|
||||
dto.setPhoto(PhotoMapper.toDTO(p.getPhoto()));
|
||||
dto.setPermission(p.getPermission().name());
|
||||
|
||||
return dto;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package local.epul4a.fotosharing.mapper;
|
||||
|
||||
import local.epul4a.fotosharing.dto.PhotoDTO;
|
||||
import local.epul4a.fotosharing.dto.UtilisateurDTO;
|
||||
import local.epul4a.fotosharing.model.Photo;
|
||||
import local.epul4a.fotosharing.model.Utilisateur;
|
||||
|
||||
public class PhotoMapper {
|
||||
public static PhotoDTO toDTO(Photo p) {
|
||||
if (p == null) return null;
|
||||
PhotoDTO dto = new PhotoDTO();
|
||||
dto.setId(p.getId());
|
||||
dto.setNomFichierOriginal(p.getNomFichierOriginal());
|
||||
dto.setUuidFichier(p.getUuidFichier());
|
||||
dto.setDateUpload(p.getDateUpload());
|
||||
dto.setVisibilite(p.getVisibilite().name());
|
||||
Utilisateur u = p.getProprietaire();
|
||||
if (u != null) {
|
||||
UtilisateurDTO uDTO = new UtilisateurDTO();
|
||||
uDTO.setId(u.getId());
|
||||
uDTO.setEmail(u.getEmail());
|
||||
uDTO.setNom(u.getNom());
|
||||
uDTO.setPrenom(u.getPrenom());
|
||||
dto.setProprietaire(uDTO);
|
||||
}
|
||||
return dto;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package local.epul4a.fotosharing.mapper;
|
||||
|
||||
import local.epul4a.fotosharing.dto.UtilisateurDTO;
|
||||
import local.epul4a.fotosharing.model.Utilisateur;
|
||||
|
||||
public class UtilisateurMapper {
|
||||
|
||||
public static UtilisateurDTO toDTO(Utilisateur u) {
|
||||
if (u == null) return null;
|
||||
UtilisateurDTO dto = new UtilisateurDTO();
|
||||
dto.setId(u.getId());
|
||||
dto.setEmail(u.getEmail());
|
||||
dto.setNom(u.getNom());
|
||||
dto.setPrenom(u.getPrenom());
|
||||
return dto;
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,11 @@ import lombok.Setter;
|
||||
@Getter
|
||||
@Setter
|
||||
public class Partage {
|
||||
public enum Permission {
|
||||
READ,
|
||||
COMMENT,
|
||||
ADMIN
|
||||
}
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@@ -21,5 +26,7 @@ public class Partage {
|
||||
@JoinColumn(name = "id_utilisateur")
|
||||
private Utilisateur utilisateur;
|
||||
|
||||
// Getters & Setters
|
||||
@Enumerated(EnumType.STRING)
|
||||
private Permission permission = Permission.READ;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package local.epul4a.fotosharing.service;
|
||||
|
||||
import local.epul4a.fotosharing.dto.CommentaireDTO;
|
||||
import local.epul4a.fotosharing.model.Commentaire;
|
||||
import org.springframework.data.domain.Page;
|
||||
|
||||
@@ -8,6 +9,6 @@ import java.util.List;
|
||||
public interface CommentaireService {
|
||||
List<Commentaire> listByPhoto(Long photoId);
|
||||
void addComment(Long photoId, String email, String contenu);
|
||||
Page<Commentaire> listByPhoto(Long photoId, int page, int size);
|
||||
Page<CommentaireDTO> listByPhoto(Long photoId, int page, int size);
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package local.epul4a.fotosharing.service;
|
||||
|
||||
import local.epul4a.fotosharing.dto.PartageDTO;
|
||||
import java.util.List;
|
||||
|
||||
public interface PartageService {
|
||||
void share(Long photoId, String targetEmail, String permission, String ownerEmail);
|
||||
void unshare(Long photoId, String targetEmail);
|
||||
List<PartageDTO> getPartagesForPhoto(Long photoId);
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
package local.epul4a.fotosharing.service;
|
||||
|
||||
import local.epul4a.fotosharing.dto.PhotoDTO;
|
||||
import local.epul4a.fotosharing.model.Photo;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import java.io.IOException;
|
||||
@@ -8,19 +10,14 @@ import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
public interface PhotoService {
|
||||
Photo store(MultipartFile file, String visibilite, String ownerEmail) throws IOException;
|
||||
Path loadAsPath(String uuidFile);
|
||||
List<Photo> listByOwner(String email);
|
||||
List<Photo> listPublicPhotos();
|
||||
List<Photo> listSharedWith(String email);
|
||||
List<Photo> listPrivatePhotos(String email);
|
||||
List<Photo> listPublicPhotos(String email);
|
||||
void unshare(Long photoId, String email);
|
||||
Page<Photo> listPublic(int page, int size);
|
||||
Page<Photo> listPrivatePhotos(String email, int page, int size);
|
||||
Page<Photo> listPublicPhotos(String email, int page, int size);
|
||||
Page<Photo> listSharedWith(String email, int page, int size);
|
||||
Page<Photo> listSharedPhotos(String email, int page, int size);
|
||||
PhotoDTO store(MultipartFile file, String visibilite, String ownerEmail);
|
||||
PhotoDTO getPhotoById(Long id);
|
||||
Resource loadAsResource(String uuidFichier);
|
||||
Page<PhotoDTO> listPublic(int page, int size);
|
||||
Page<PhotoDTO> listPrivatePhotos(String email, int page, int size);
|
||||
Page<PhotoDTO> listPublicPhotos(String email, int page, int size);
|
||||
Page<PhotoDTO> listSharedWith(String email, int page, int size);
|
||||
Page<PhotoDTO> listSharedPhotos(String email, int page, int size);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package local.epul4a.fotosharing.service;
|
||||
|
||||
import local.epul4a.fotosharing.dto.UtilisateurDTO;
|
||||
|
||||
public interface UtilisateurService {
|
||||
UtilisateurDTO findByEmail(String email);
|
||||
boolean existsByEmail(String email);
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package local.epul4a.fotosharing.service.impl;
|
||||
|
||||
import local.epul4a.fotosharing.dto.CommentaireDTO;
|
||||
import local.epul4a.fotosharing.mapper.CommentaireMapper;
|
||||
import local.epul4a.fotosharing.model.Commentaire;
|
||||
import local.epul4a.fotosharing.model.Photo;
|
||||
import local.epul4a.fotosharing.model.Utilisateur;
|
||||
@@ -51,9 +53,14 @@ public class CommentaireServiceImpl implements CommentaireService {
|
||||
commentaireRepository.save(c);
|
||||
}
|
||||
@Override
|
||||
public Page<Commentaire> listByPhoto(Long photoId, int page, int size) {
|
||||
public Page<CommentaireDTO> listByPhoto(Long photoId, int page, int size) {
|
||||
Pageable pageable = PageRequest.of(page, size);
|
||||
return commentaireRepository.findByPhoto_Id(photoId, pageable);
|
||||
|
||||
Page<Commentaire> commentaires =
|
||||
commentaireRepository.findByPhoto_Id(photoId, pageable);
|
||||
|
||||
return commentaires.map(CommentaireMapper::toDTO);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
package local.epul4a.fotosharing.service.impl;
|
||||
|
||||
import local.epul4a.fotosharing.dto.PartageDTO;
|
||||
import local.epul4a.fotosharing.mapper.PartageMapper;
|
||||
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.PartageService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class PartageServiceImpl implements PartageService {
|
||||
|
||||
private final PartageRepository partageRepository;
|
||||
private final PhotoRepository photoRepository;
|
||||
private final UtilisateurRepository utilisateurRepository;
|
||||
|
||||
public PartageServiceImpl(
|
||||
PartageRepository partageRepository,
|
||||
PhotoRepository photoRepository,
|
||||
UtilisateurRepository utilisateurRepository
|
||||
) {
|
||||
this.partageRepository = partageRepository;
|
||||
this.photoRepository = photoRepository;
|
||||
this.utilisateurRepository = utilisateurRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PartageDTO> getPartagesForPhoto(Long photoId) {
|
||||
return partageRepository.findByPhoto_Id(photoId)
|
||||
.stream()
|
||||
.map(PartageMapper::toDTO)
|
||||
.toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void share(Long photoId, String targetEmail, String permissionStr, String ownerEmail) {
|
||||
|
||||
Photo photo = photoRepository.findById(photoId)
|
||||
.orElseThrow(() -> new RuntimeException("Photo introuvable"));
|
||||
|
||||
if (!photo.getProprietaire().getEmail().equals(ownerEmail))
|
||||
throw new RuntimeException("Vous n'êtes pas propriétaire");
|
||||
|
||||
Utilisateur target = utilisateurRepository.findByEmail(targetEmail)
|
||||
.orElseThrow(() -> new RuntimeException("Utilisateur introuvable"));
|
||||
|
||||
if (partageRepository.existsByPhoto_IdAndUtilisateur_Email(photoId, targetEmail))
|
||||
return;
|
||||
|
||||
Partage.Permission permission = Partage.Permission.valueOf(permissionStr);
|
||||
|
||||
Partage partage = new Partage();
|
||||
partage.setPhoto(photo);
|
||||
partage.setUtilisateur(target);
|
||||
partage.setPermission(permission);
|
||||
|
||||
partageRepository.save(partage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unshare(Long photoId, String targetEmail) {
|
||||
|
||||
Partage partage = partageRepository.findByPhoto_Id(photoId)
|
||||
.stream()
|
||||
.filter(p -> p.getUtilisateur().getEmail().equals(targetEmail))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
|
||||
if (partage != null)
|
||||
partageRepository.delete(partage);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package local.epul4a.fotosharing.service.impl;
|
||||
|
||||
import local.epul4a.fotosharing.dto.PhotoDTO;
|
||||
import local.epul4a.fotosharing.mapper.PhotoMapper;
|
||||
import local.epul4a.fotosharing.model.Partage;
|
||||
import local.epul4a.fotosharing.model.Photo;
|
||||
import local.epul4a.fotosharing.model.Utilisateur;
|
||||
@@ -8,15 +10,15 @@ import local.epul4a.fotosharing.repository.PhotoRepository;
|
||||
import local.epul4a.fotosharing.repository.UtilisateurRepository;
|
||||
import local.epul4a.fotosharing.service.PhotoService;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.UrlResource;
|
||||
import org.springframework.data.domain.*;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.nio.file.*;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
@@ -27,134 +29,130 @@ public class PhotoServiceImpl implements PhotoService {
|
||||
|
||||
@Value("${file.upload-dir}")
|
||||
private String uploadDir;
|
||||
|
||||
private final PhotoRepository photoRepository;
|
||||
private final UtilisateurRepository utilisateurRepository;
|
||||
private final PartageRepository partageRepository;
|
||||
|
||||
public PhotoServiceImpl(PhotoRepository photoRepository, UtilisateurRepository utilisateurRepository, PartageRepository partageRepository) {
|
||||
public PhotoServiceImpl(
|
||||
PhotoRepository photoRepository,
|
||||
UtilisateurRepository utilisateurRepository,
|
||||
PartageRepository partageRepository) {
|
||||
this.photoRepository = photoRepository;
|
||||
this.utilisateurRepository = utilisateurRepository;
|
||||
this.partageRepository = partageRepository;
|
||||
}
|
||||
|
||||
|
||||
//============= STORE PHOTO =============================
|
||||
@Override
|
||||
public Photo store(MultipartFile file, String visibilite, String ownerEmail) throws IOException {
|
||||
if (file.isEmpty()) throw new IOException("Fichier vide");
|
||||
|
||||
// Vérifier taille / type si besoin (ici basique)
|
||||
String original = StringUtils.cleanPath(file.getOriginalFilename());
|
||||
String uuid = UUID.randomUUID().toString() + "-" + original;
|
||||
|
||||
Path uploadPath = Paths.get(uploadDir);
|
||||
if (!Files.exists(uploadPath)) Files.createDirectories(uploadPath);
|
||||
|
||||
Path target = uploadPath.resolve(uuid);
|
||||
Files.copy(file.getInputStream(), target, StandardCopyOption.REPLACE_EXISTING);
|
||||
|
||||
Photo p = new Photo();
|
||||
p.setNomFichierOriginal(original);
|
||||
p.setUuidFichier(uuid);
|
||||
p.setDateUpload(LocalDateTime.now());
|
||||
p.setVisibilite(Photo.Visibilite.valueOf(visibilite));
|
||||
Utilisateur u = utilisateurRepository.findByEmail(ownerEmail).orElseThrow(() -> new IOException("Utilisateur introuvable"));
|
||||
p.setProprietaire(u);
|
||||
|
||||
return photoRepository.save(p);
|
||||
public PhotoDTO store(MultipartFile file, String visibilite, String ownerEmail) {
|
||||
try {
|
||||
if (file.isEmpty()) throw new IOException("Fichier vide");
|
||||
String original = StringUtils.cleanPath(file.getOriginalFilename());
|
||||
String uuid = UUID.randomUUID() + "-" + original;
|
||||
Path uploadPath = Paths.get(uploadDir);
|
||||
if (!Files.exists(uploadPath))
|
||||
Files.createDirectories(uploadPath);
|
||||
Files.copy(file.getInputStream(),
|
||||
uploadPath.resolve(uuid),
|
||||
StandardCopyOption.REPLACE_EXISTING);
|
||||
Utilisateur owner = utilisateurRepository.findByEmail(ownerEmail)
|
||||
.orElseThrow(() -> new RuntimeException("Utilisateur introuvable"));
|
||||
Photo p = new Photo();
|
||||
p.setNomFichierOriginal(original);
|
||||
p.setUuidFichier(uuid);
|
||||
p.setVisibilite(Photo.Visibilite.valueOf(visibilite));
|
||||
p.setDateUpload(LocalDateTime.now());
|
||||
p.setProprietaire(owner);
|
||||
return PhotoMapper.toDTO(photoRepository.save(p));
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException("Erreur upload : " + ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path loadAsPath(String uuidFile) {
|
||||
return Paths.get(uploadDir).resolve(uuidFile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Photo> listByOwner(String email) {
|
||||
return photoRepository.findByProprietaire_Email(email);
|
||||
}
|
||||
|
||||
//============= GET PHOTO BY ID ==========================
|
||||
@Override
|
||||
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();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Photo> listPrivatePhotos(String email) {
|
||||
return photoRepository.findByProprietaire_Email(email).stream()
|
||||
.filter(p -> p.getVisibilite() == Photo.Visibilite.PRIVATE)
|
||||
.toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Photo> listPublicPhotos(String email) {
|
||||
return photoRepository.findByProprietaire_Email(email).stream()
|
||||
.filter(p -> p.getVisibilite() == Photo.Visibilite.PUBLIC)
|
||||
.toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unshare(Long photoId, String email) {
|
||||
Partage p = partageRepository.findByPhoto_Id(photoId).stream()
|
||||
.filter(x -> x.getUtilisateur().getEmail().equals(email))
|
||||
.findFirst()
|
||||
public PhotoDTO getPhotoById(Long id) {
|
||||
return photoRepository.findById(id)
|
||||
.map(PhotoMapper::toDTO)
|
||||
.orElse(null);
|
||||
if (p != null) partageRepository.delete(p);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//============= LOAD RESOURCE ============================
|
||||
@Override
|
||||
public Page<Photo> listPublic(int page, int size) {
|
||||
public Resource loadAsResource(String uuidFichier) {
|
||||
try {
|
||||
Path file = Paths.get(uploadDir).resolve(uuidFichier);
|
||||
Resource resource = new UrlResource(file.toUri());
|
||||
if (!resource.exists() || !resource.isReadable())
|
||||
throw new RuntimeException("Impossible de lire le fichier : " + uuidFichier);
|
||||
return resource;
|
||||
} catch (MalformedURLException e) {
|
||||
throw new RuntimeException("Fichier introuvable : " + uuidFichier);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//============= LIST PUBLIC PHOTOS =======================
|
||||
@Override
|
||||
public Page<PhotoDTO> listPublic(int page, int size) {
|
||||
Pageable pageable = PageRequest.of(page, size);
|
||||
return photoRepository.findByVisibilite(Photo.Visibilite.PUBLIC, pageable);
|
||||
return photoRepository
|
||||
.findByVisibilite(Photo.Visibilite.PUBLIC, pageable)
|
||||
.map(PhotoMapper::toDTO);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//============= PRIVATE PHOTOS OF USER ===================
|
||||
@Override
|
||||
public Page<Photo> listPrivatePhotos(String email, int page, int size) {
|
||||
public Page<PhotoDTO> listPrivatePhotos(String email, int page, int size) {
|
||||
Pageable pageable = PageRequest.of(page, size);
|
||||
return photoRepository.findByProprietaire_EmailAndVisibilite(
|
||||
email,
|
||||
Photo.Visibilite.PRIVATE,
|
||||
pageable
|
||||
);
|
||||
return photoRepository
|
||||
.findByProprietaire_EmailAndVisibilite(email, Photo.Visibilite.PRIVATE, pageable)
|
||||
.map(PhotoMapper::toDTO);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//============= PUBLIC PHOTOS OF USER ====================
|
||||
@Override
|
||||
public Page<Photo> listPublicPhotos(String email, int page, int size) {
|
||||
public Page<PhotoDTO> listPublicPhotos(String email, int page, int size) {
|
||||
Pageable pageable = PageRequest.of(page, size);
|
||||
return photoRepository.findByProprietaire_EmailAndVisibilite(
|
||||
email,
|
||||
Photo.Visibilite.PUBLIC,
|
||||
pageable
|
||||
);
|
||||
return photoRepository
|
||||
.findByProprietaire_EmailAndVisibilite(email, Photo.Visibilite.PUBLIC, pageable)
|
||||
.map(PhotoMapper::toDTO);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//============= PHOTOS SHARED WITH USER ==================
|
||||
@Override
|
||||
public Page<Photo> listSharedWith(String email, int page, int size) {
|
||||
List<Partage> partages = partageRepository.findByUtilisateur_Email(email);
|
||||
List<Photo> photos = partages.stream().map(Partage::getPhoto).toList();
|
||||
// convertir list en page manuellement
|
||||
public Page<PhotoDTO> listSharedWith(String email, int page, int size) {
|
||||
List<PhotoDTO> photos =
|
||||
partageRepository.findByUtilisateur_Email(email)
|
||||
.stream()
|
||||
.map(Partage::getPhoto)
|
||||
.map(PhotoMapper::toDTO)
|
||||
.toList();
|
||||
int start = page * size;
|
||||
int end = Math.min(start + size, photos.size());
|
||||
List<Photo> sublist = photos.subList(start, end);
|
||||
return new PageImpl<>(sublist, PageRequest.of(page, size), photos.size());
|
||||
List<PhotoDTO> sub = photos.subList(start, end);
|
||||
return new PageImpl<>(sub, PageRequest.of(page, size), photos.size());
|
||||
}
|
||||
|
||||
|
||||
//============= PHOTOS SET AS SHARED BY USER =============
|
||||
@Override
|
||||
public Page<Photo> listSharedPhotos(String email, int page, int size) {
|
||||
public Page<PhotoDTO> listSharedPhotos(String email, int page, int size) {
|
||||
Pageable pageable = PageRequest.of(page, size);
|
||||
return photoRepository.findByProprietaire_EmailAndVisibilite(
|
||||
email,
|
||||
Photo.Visibilite.SHARED,
|
||||
pageable
|
||||
);
|
||||
return photoRepository
|
||||
.findByProprietaire_EmailAndVisibilite(email, Photo.Visibilite.SHARED, pageable)
|
||||
.map(PhotoMapper::toDTO);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package local.epul4a.fotosharing.service.impl;
|
||||
|
||||
import local.epul4a.fotosharing.dto.UtilisateurDTO;
|
||||
import local.epul4a.fotosharing.mapper.UtilisateurMapper;
|
||||
import local.epul4a.fotosharing.model.Utilisateur;
|
||||
import local.epul4a.fotosharing.repository.UtilisateurRepository;
|
||||
import local.epul4a.fotosharing.service.UtilisateurService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class UtilisateurServiceImpl implements UtilisateurService {
|
||||
|
||||
private final UtilisateurRepository utilisateurRepository;
|
||||
|
||||
public UtilisateurServiceImpl(UtilisateurRepository utilisateurRepository) {
|
||||
this.utilisateurRepository = utilisateurRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UtilisateurDTO findByEmail(String email) {
|
||||
Utilisateur u = utilisateurRepository.findByEmail(email)
|
||||
.orElse(null);
|
||||
return UtilisateurMapper.toDTO(u);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean existsByEmail(String email) {
|
||||
return utilisateurRepository.findByEmail(email).isPresent();
|
||||
}
|
||||
}
|
||||
@@ -8,9 +8,6 @@
|
||||
<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(mesPhotos)}">
|
||||
<p>Vous n'avez pas encore de photos.</p>
|
||||
</div>
|
||||
<h2>Mes photos privées</h2>
|
||||
<div>
|
||||
<a th:each="p : ${photosPrivees.content}"
|
||||
@@ -52,10 +49,21 @@
|
||||
</div>
|
||||
<div>
|
||||
<a th:if="${mesPhotosPartagees.hasPrevious()}"
|
||||
th:href="@{/mes-photos(pageMesPartagees=${pageMesPartagees - 1})}">⬅</a>
|
||||
th:href="@{/mes-photos(
|
||||
pagePrivees=${pagePrivees},
|
||||
pagePubliques=${pagePubliques},
|
||||
pagePartagees=${pagePartagees},
|
||||
pageMesPartagees=${pageMesPartagees - 1}
|
||||
)}">⬅</a>
|
||||
<span th:text="'Page ' + (${pageMesPartagees}+1)"></span>
|
||||
<a th:if="${mesPhotosPartagees.hasNext()}"
|
||||
th:href="@{/mes-photos(pageMesPartagees=${pageMesPartagees + 1})}">➡</a>
|
||||
th:href="@{/mes-photos(
|
||||
pagePrivees=${pagePrivees},
|
||||
pagePubliques=${pagePubliques},
|
||||
pagePartagees=${pagePartagees},
|
||||
pageMesPartagees=${pageMesPartagees + 1}
|
||||
)}">➡</a>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
<ul>
|
||||
<li th:each="p : ${partages}">
|
||||
<span th:text="${p.utilisateur.email}"></span>
|
||||
—
|
||||
<span th:text="${p.permission}"></span>
|
||||
<a th:href="@{'/photo/' + ${photo.id} + '/unshare/' + ${p.utilisateur.email}}"
|
||||
style="color:red;">Retirer</a>
|
||||
</li>
|
||||
@@ -43,6 +45,12 @@
|
||||
<form th:action="@{'/photo/' + ${photo.id} + '/share'}" method="post">
|
||||
<label>Email de l'utilisateur :</label>
|
||||
<input type="email" name="email" required />
|
||||
<label>Permission :</label>
|
||||
<select name="permission">
|
||||
<option value="READ">Lecture</option>
|
||||
<option value="COMMENT">Commenter</option>
|
||||
<option value="ADMIN">Administrer</option>
|
||||
</select>
|
||||
<button type="submit">Partager</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user