Commit ab607cc1 by Rubén Ramírez

fix: [Recursos]: Actualizada la manera de trabajar con las fotos para…

fix: [Recursos]: Actualizada la manera de trabajar con las fotos para almacenarlas también en la BBDD
parent 3a98e108
......@@ -6,7 +6,6 @@ import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDate;
import java.util.List;
......@@ -28,17 +27,16 @@ public class RepositorioRecurso {
@Transactional(readOnly = true)
public List<Recurso> buscarPorTitulo(String titulo) {
return em.createQuery(
"SELECT r FROM Recurso r WHERE LOWER(r.titulo) LIKE LOWER(:titulo)",
"SELECT r FROM Recurso r WHERE LOWER(r.titulo) LIKE LOWER(:titulo)",
Recurso.class)
.setParameter("titulo", "%" + titulo + "%")
.getResultList();
}
@Transactional(readOnly = true)
public List<Recurso> buscarPorAutor(String autor) {
return em.createQuery(
"SELECT r FROM Recurso r WHERE LOWER(r.autor) LIKE LOWER(:autor)",
"SELECT r FROM Recurso r WHERE LOWER(r.autor) LIKE LOWER(:autor)",
Recurso.class)
.setParameter("autor", "%" + autor + "%")
.getResultList();
......@@ -47,7 +45,7 @@ public class RepositorioRecurso {
@Transactional(readOnly = true)
public List<Recurso> buscarPorGenero(Genero genero) {
return em.createQuery(
"SELECT r FROM Recurso r JOIN r.generos g WHERE g = :genero",
"SELECT r FROM Recurso r JOIN r.generos g WHERE g = :genero",
Recurso.class)
.setParameter("genero", genero)
.getResultList();
......@@ -56,7 +54,7 @@ public class RepositorioRecurso {
@Transactional(readOnly = true)
public List<Recurso> buscarPorRangoFechas(LocalDate fechaInicio, LocalDate fechaFin) {
return em.createQuery(
"SELECT r FROM Recurso r WHERE r.fechaPublicacion BETWEEN :inicio AND :fin",
"SELECT r FROM Recurso r WHERE r.fechaPublicacion BETWEEN :inicio AND :fin",
Recurso.class)
.setParameter("inicio", fechaInicio)
.setParameter("fin", fechaFin)
......
package com.ujaen.tfg.mangaffinity.rest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.ujaen.tfg.mangaffinity.entidades.BibliotecaPersonal;
import com.ujaen.tfg.mangaffinity.entidades.BibliotecaPersonalRecurso;
import com.ujaen.tfg.mangaffinity.entidades.Categoria;
import com.ujaen.tfg.mangaffinity.entidades.Recurso;
import com.ujaen.tfg.mangaffinity.excepciones.RecursoNoExiste;
import com.ujaen.tfg.mangaffinity.rest.DTO.DTORecursoEnBiblioteca;
import com.ujaen.tfg.mangaffinity.rest.DTO.Mapper;
import com.ujaen.tfg.mangaffinity.servicios.ServicioBibliotecaPersonal;
import com.ujaen.tfg.mangaffinity.servicios.ServicioRecursos;
import com.ujaen.tfg.mangaffinity.servicios.ServicioUsuarios;
......@@ -15,14 +12,14 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.Base64;
import java.util.List;
import java.util.stream.Collectors;
@RestController
@RequestMapping("/biblioteca")
public class BibliotecaPersonalController {
private static final Logger logger = LoggerFactory.getLogger(BibliotecaPersonalController.class);
@Autowired
private ServicioBibliotecaPersonal servicioBibliotecaPersonal;
......@@ -32,9 +29,6 @@ public class BibliotecaPersonalController {
@Autowired
private ServicioUsuarios servicioUsuarios;
@Autowired
private Mapper mapper;
@PostMapping("/{usuarioId}/recursos/{recursoId}/categoria")
public ResponseEntity<String> anadirRecursoBiblioteca(
@PathVariable Long usuarioId,
......@@ -51,7 +45,6 @@ public class BibliotecaPersonalController {
return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
}
boolean yaExiste = servicioBibliotecaPersonal.listarPorCategoria(biblioteca.getId(), dtoRecursoEnBiblioteca.getCategoria())
.stream()
.anyMatch(bpr -> bpr.getRecurso().getId().equals(recursoId));
......@@ -67,11 +60,9 @@ public class BibliotecaPersonalController {
}
}
@GetMapping("/{usuarioId}/recursos/categoria/{categoria}")
public ResponseEntity<List<DTORecursoEnBiblioteca>> listarRecursosPorCategoria(
@PathVariable Long usuarioId, @PathVariable String categoria) { // 🔥 Ahora es String
@PathVariable Long usuarioId, @PathVariable String categoria) {
try {
BibliotecaPersonal biblioteca = servicioUsuarios.obtenerBibliotecaDeUsuario(usuarioId);
if (biblioteca == null) {
......@@ -82,17 +73,23 @@ public class BibliotecaPersonalController {
try {
categoriaEnum = Categoria.valueOf(categoria.toUpperCase());
} catch (IllegalArgumentException e) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(null); // ⚠ Si la categoría no es válida
return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
}
List<BibliotecaPersonalRecurso> recursos = servicioBibliotecaPersonal.listarPorCategoria(biblioteca.getId(), categoriaEnum);
List<DTORecursoEnBiblioteca> dtoRecursos = recursos.stream()
.map(bpr -> new DTORecursoEnBiblioteca(
bpr.getRecurso().getId(),
bpr.getRecurso().getTitulo(),
bpr.getCategoria(),
bpr.getRecurso().getFotoUrl() // 🔥 Aquí añadimos la imagen
))
.map(bpr -> {
String fotoBase64 = (bpr.getRecurso().getFoto() != null && bpr.getRecurso().getFoto().length > 0)
? "data:image/jpeg;base64," + Base64.getEncoder().encodeToString(bpr.getRecurso().getFoto())
: null;
return new DTORecursoEnBiblioteca(
bpr.getRecurso().getId(),
bpr.getRecurso().getTitulo(),
bpr.getCategoria(),
fotoBase64
);
})
.collect(Collectors.toList());
......@@ -102,22 +99,6 @@ public class BibliotecaPersonalController {
}
}
@PutMapping("/{usuarioId}/recursos/{recursoId}/categoria")
public ResponseEntity<String> cambiarCategoria(
@PathVariable Long usuarioId,
@PathVariable Long recursoId,
@RequestBody DTORecursoEnBiblioteca dtoRecurso) {
try {
BibliotecaPersonal biblioteca = servicioUsuarios.obtenerBibliotecaDeUsuario(usuarioId);
if (biblioteca == null) return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
servicioBibliotecaPersonal.cambiarCategoriaRecurso(biblioteca.getId(), recursoId, dtoRecurso.getCategoria());
return ResponseEntity.status(HttpStatus.OK).build();
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}
@DeleteMapping("/{usuarioId}/recursos/{recursoId}")
public ResponseEntity<String> eliminarRecursoDeBiblioteca(
@PathVariable Long usuarioId,
......@@ -127,7 +108,7 @@ public class BibliotecaPersonalController {
if (biblioteca == null) return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
servicioBibliotecaPersonal.eliminarRecursoDeBiblioteca(biblioteca.getId(), recursoId);
return ResponseEntity.status(HttpStatus.NO_CONTENT).build(); // Código 204 para eliminación exitosa
return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
......@@ -137,38 +118,44 @@ public class BibliotecaPersonalController {
public ResponseEntity<DTORecursoEnBiblioteca> obtenerRecursoEnBiblioteca(
@PathVariable Long usuarioId, @PathVariable Long recursoId) {
try {
logger.info("Recibiendo solicitud para obtener recurso con ID: {} para usuario con ID: {}", recursoId, usuarioId);
// Obtener la biblioteca personal del usuario
BibliotecaPersonal biblioteca = servicioUsuarios.obtenerBibliotecaDeUsuario(usuarioId);
if (biblioteca == null) {
logger.warn("No se encontró la biblioteca para el usuario con ID: {}", usuarioId);
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null); // Si no existe la biblioteca del usuario
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
}
// Buscar el recurso dentro de la biblioteca del usuario
BibliotecaPersonalRecurso bibliotecaPersonalRecurso = servicioBibliotecaPersonal.buscarRecursoEnBiblioteca(biblioteca.getId(), recursoId);
if (bibliotecaPersonalRecurso == null) {
logger.warn("No se encontró el recurso con ID: {} en la biblioteca del usuario con ID: {}", recursoId, usuarioId);
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null); // Si no se encuentra el recurso en la biblioteca
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
}
// Mapear el recurso encontrado al DTO para retornar
DTORecursoEnBiblioteca dtoRecursoEnBiblioteca = new DTORecursoEnBiblioteca(
bibliotecaPersonalRecurso.getRecurso().getId(),
bibliotecaPersonalRecurso.getRecurso().getTitulo(),
bibliotecaPersonalRecurso.getCategoria(),
bibliotecaPersonalRecurso.getRecurso().getFotoUrl()
(bibliotecaPersonalRecurso.getRecurso().getFoto() != null)
? Base64.getEncoder().encodeToString(bibliotecaPersonalRecurso.getRecurso().getFoto())
: null
);
logger.info("Recurso con ID: {} encontrado para el usuario con ID: {}", recursoId, usuarioId);
return ResponseEntity.ok(dtoRecursoEnBiblioteca);
} catch (Exception e) {
logger.error("Error inesperado al obtener el recurso con ID: {} para el usuario con ID: {}", recursoId, usuarioId, e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(); // Si ocurre algún error inesperado
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}
@PutMapping("/{usuarioId}/recursos/{recursoId}/categoria")
public ResponseEntity<String> cambiarCategoria(
@PathVariable Long usuarioId,
@PathVariable Long recursoId,
@RequestBody DTORecursoEnBiblioteca dtoRecurso) {
try {
BibliotecaPersonal biblioteca = servicioUsuarios.obtenerBibliotecaDeUsuario(usuarioId);
if (biblioteca == null) return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
}
servicioBibliotecaPersonal.cambiarCategoriaRecurso(biblioteca.getId(), recursoId, dtoRecurso.getCategoria());
return ResponseEntity.status(HttpStatus.OK).build();
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}
}
package com.ujaen.tfg.mangaffinity.rest.DTO;
import com.ujaen.tfg.mangaffinity.entidades.Genero;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.time.LocalDate;
import java.util.HashSet;
import java.util.Set;
@Getter
......@@ -17,19 +15,11 @@ import java.util.Set;
@AllArgsConstructor
public class DTORecurso {
private Long id;
@NotBlank
private String titulo;
private String descripcion;
@NotNull
private LocalDate fechaPublicacion;
@NotBlank
private String autor;
private String fotoUrl;
private Set<Genero> generos = new HashSet<>();
private String fotoBase64;
private Set<Genero> generos;
}
......@@ -11,16 +11,8 @@ import lombok.Setter;
@NoArgsConstructor
@AllArgsConstructor
public class DTORecursoEnBiblioteca {
private Long usuarioId;
private Long recursoId;
private String titulo;
private Categoria categoria;
private String fotoUrl;
public DTORecursoEnBiblioteca(Long recursoId, String titulo, Categoria categoria, String fotoUrl) {
this.recursoId = recursoId;
this.titulo = titulo;
this.categoria = categoria;
this.fotoUrl = fotoUrl;
}
private String fotoBase64;
}
package com.ujaen.tfg.mangaffinity.rest;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.net.MalformedURLException;
import java.nio.file.*;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
@RestController
@RequestMapping("/uploads")
public class UploadController {
private final Path uploadDir = Paths.get("uploads");
@GetMapping("/{filename:.+}")
public ResponseEntity<Resource> getFile(@PathVariable String filename) {
try {
Path file = uploadDir.resolve(filename);
Resource resource = new UrlResource(file.toUri());
if (resource.exists() || resource.isReadable()) {
String contentType = "application/octet-stream";
if (filename.endsWith(".png")) contentType = "image/png";
else if (filename.endsWith(".jpg") || filename.endsWith(".jpeg")) contentType = "image/jpeg";
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"" + resource.getFilename() + "\"")
.header(HttpHeaders.CONTENT_TYPE, contentType)
.body(resource);
} else {
return ResponseEntity.notFound().build();
}
} catch (MalformedURLException e) {
return ResponseEntity.badRequest().build();
}
}
@PostMapping
public ResponseEntity<String> uploadFile(@RequestParam("foto") MultipartFile foto) {
try {
if (foto.isEmpty()) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
}
String contentType = foto.getContentType();
if (contentType == null || (!contentType.equals("image/jpeg") && !contentType.equals("image/png"))) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
}
if (!Files.exists(uploadDir)) {
Files.createDirectories(uploadDir);
}
Path path = uploadDir.resolve(foto.getOriginalFilename());
Files.copy(foto.getInputStream(), path, StandardCopyOption.REPLACE_EXISTING);
return ResponseEntity.ok(foto.getOriginalFilename());
} catch (IOException e) {
e.printStackTrace();
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}
}
......@@ -37,8 +37,7 @@ public class ServicioSeguridad {
return config;
}))
.authorizeHttpRequests(request -> request
.requestMatchers(HttpMethod.GET, "/uploads/**").permitAll()
.requestMatchers(HttpMethod.POST, "/usuarios/{email}").permitAll() // Permitir login sin autenticación
.requestMatchers(HttpMethod.POST, "/usuarios/{email}").permitAll()
.requestMatchers(HttpMethod.GET, "/usuarios/email/{email}").permitAll()
.requestMatchers(HttpMethod.POST, "/usuarios/").permitAll()
.requestMatchers(HttpMethod.GET, "/actuator/health").permitAll()
......@@ -65,7 +64,7 @@ public class ServicioSeguridad {
.anyRequest().authenticated()
)
.addFilterBefore(new JwtFilter(jwtUtil), UsernamePasswordAuthenticationFilter.class) // Usar solo JWT
.addFilterBefore(new JwtFilter(jwtUtil), UsernamePasswordAuthenticationFilter.class)
.build();
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment