From f978887b6b63bf8e04c88d5ec3a9bf742e33a4cd Mon Sep 17 00:00:00 2001 From: Samuel Modesto Date: Tue, 25 Nov 2025 12:08:34 -0300 Subject: [PATCH 01/15] heroku config --- cadastral/Dockerfile | 52 +++++++++++-------- .../src/main/resources/application-heroku.yml | 46 ++++++++++++++++ cadastral/src/main/resources/application.yml | 13 ++--- 3 files changed, 82 insertions(+), 29 deletions(-) create mode 100644 cadastral/src/main/resources/application-heroku.yml diff --git a/cadastral/Dockerfile b/cadastral/Dockerfile index 76f76bb7..fac89c27 100644 --- a/cadastral/Dockerfile +++ b/cadastral/Dockerfile @@ -1,21 +1,31 @@ -#FROM openjdk:17-alpine -#MAINTAINER com.mateusbalda -#VOLUME /tmp -#EXPOSE 8081 -# -#COPY CrudService/target/*.jar /crud-service.jar -# -#ENTRYPOINT ["java","-jar","-Dspring.profiles.active=docker-demo", "/crud-service.jar"] - -## In this way the file, creates the image along with maven -FROM maven:3.6-openjdk-17-slim AS MAVEN_BUILD -COPY CrudService/pom.xml /build/ -COPY CrudService/src /build/src/ -WORKDIR /build/ -RUN mvn package -DskipTests - -FROM openjdk:17-alpine -MAINTAINER com.mateusbalda -EXPOSE 8081 -COPY --from=MAVEN_BUILD /build/target/*.jar imobiliaria.jar -ENTRYPOINT ["java","-jar","-Dspring.profiles.active=docker-demo","/imobiliaria.jar"] +# ---------- stage 1: build ---------- +FROM maven:3.9.6-eclipse-temurin-21 AS build + +WORKDIR /app + +# Copiar apenas o pom para aproveitar o cache do Maven +COPY pom.xml . +RUN mvn -q -DskipTests dependency:go-offline + +# Copiar código restante +COPY . . + +# Gerar o JAR (sem testes para agilizar) +RUN mvn -q clean package -DskipTests + + +# ---------- stage 2: runtime ---------- +FROM eclipse-temurin:21-jre AS runtime + +WORKDIR /app + +# Copia o JAR final +COPY --from=build /app/target/*.jar app.jar + +# Heroku usa PORT, mas exponho 8080 por consistência +EXPOSE 8080 + +# Importante: garantir que a aplicação leia PORT corretamente +ENV SERVER_PORT=${PORT} + +CMD ["sh", "-c", "java -Dserver.port=$PORT -jar app.jar"] diff --git a/cadastral/src/main/resources/application-heroku.yml b/cadastral/src/main/resources/application-heroku.yml new file mode 100644 index 00000000..c25b1ebf --- /dev/null +++ b/cadastral/src/main/resources/application-heroku.yml @@ -0,0 +1,46 @@ +server: + port: ${PORT:8080} + +spring: + application: + name: cadastral + + cloud: + config: + enabled: false + import-check: + enabled: false + + config: + import: "optional:configserver:" + + data: + mongodb: + uri: ${MONGODB_URI} + + rabbitmq: + uri: ${CLOUDAMQP_URL} + + jpa: + enabled: false + + autoconfigure: + - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration + - org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration + + jmx: + enabled: false + +crud: + rabbitmq: + exchanges: + exchangeAccommodations: crud.fanout.register-accommodations + exchangeUsers: crud.fanout.register-users + queues: + accommodationQueue: crud.register-accommodations.queue + +eureka: + client: + enabled: false + register-with-eureka: false + fetch-registry: false diff --git a/cadastral/src/main/resources/application.yml b/cadastral/src/main/resources/application.yml index db40f783..cf9f19da 100644 --- a/cadastral/src/main/resources/application.yml +++ b/cadastral/src/main/resources/application.yml @@ -1,11 +1,8 @@ - spring: application: name: cadastral - config: - import: "configserver:" - cloud: - config: - discovery: - enabled: true - service-id: config-server \ No newline at end of file + +ead: + auth: + jwtSecret: a7w!z%C*F-JaNdRgUkXp2s5v8x/A?D(G+KbPeShVmYq3t6w9z$B&E)H@McQfTjWs + jwtExpirationMs: 14400000 From dcc981eef8137eb5afeb9053dc0c56d0438419f5 Mon Sep 17 00:00:00 2001 From: Samuel Modesto Date: Tue, 25 Nov 2025 15:04:53 -0300 Subject: [PATCH 02/15] heroku config --- cadastral/pom.xml | 8 +++---- .../crud/config/MongoScriptInitializer.java | 24 +++++++++++-------- .../src/main/resources/application-heroku.yml | 13 ++++++++-- cadastral/src/main/resources/application.yml | 5 +--- 4 files changed, 30 insertions(+), 20 deletions(-) diff --git a/cadastral/pom.xml b/cadastral/pom.xml index b31f3daf..4afb8e09 100644 --- a/cadastral/pom.xml +++ b/cadastral/pom.xml @@ -102,10 +102,10 @@ dotenv-java 3.0.0 - - org.springframework.cloud - spring-cloud-starter-config - + + + + diff --git a/cadastral/src/main/java/com/unipampa/crud/config/MongoScriptInitializer.java b/cadastral/src/main/java/com/unipampa/crud/config/MongoScriptInitializer.java index 1523c904..47e7ef3b 100644 --- a/cadastral/src/main/java/com/unipampa/crud/config/MongoScriptInitializer.java +++ b/cadastral/src/main/java/com/unipampa/crud/config/MongoScriptInitializer.java @@ -4,6 +4,7 @@ import com.unipampa.crud.enums.UserType; import io.github.cdimascio.dotenv.Dotenv; import org.bson.Document; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.CommandLineRunner; import org.springframework.context.annotation.Configuration; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; @@ -16,6 +17,8 @@ public class MongoScriptInitializer implements CommandLineRunner { private final PasswordEncoder passwordEncoder; private final Dotenv dotenv = Dotenv.load(); + @Value("${spring.data.mongodb.uri}") + private String mongoUri; public MongoScriptInitializer(PasswordEncoder passwordEncoder) { this.passwordEncoder = passwordEncoder; @@ -26,8 +29,8 @@ public MongoScriptInitializer(PasswordEncoder passwordEncoder) { public void run(String... args) throws Exception { System.out.println("Verificando se os dados já existem no banco..."); - try (var client = MongoClients.create("mongodb://localhost:27017")) { - var database = client.getDatabase("cadastral"); + try (var client = MongoClients.create(mongoUri)) { + var database = client.getDatabase("imovato"); var roleCollection = database.getCollection("role"); var userCollection = database.getCollection("user"); @@ -62,26 +65,27 @@ public void run(String... args) throws Exception { userCollection.insertMany(List.of( new Document("_id", "admin-1") - .append("userName", dotenv.get("ADMIN1_USERNAME")) - .append("password", passwordEncoder.encode(dotenv.get("ADMIN1_PASSWORD"))) + .append("userName", System.getenv("ADMIN1_USERNAME")) + .append("password", passwordEncoder.encode(System.getenv("ADMIN1_PASSWORD"))) .append("roles", List.of(roleAdmin)), new Document("_id", "admin-2") - .append("userName", dotenv.get("ADMIN2_USERNAME")) - .append("password", passwordEncoder.encode(dotenv.get("ADMIN2_PASSWORD"))) + .append("userName", System.getenv("ADMIN2_USERNAME")) + .append("password", passwordEncoder.encode(System.getenv("ADMIN2_PASSWORD"))) .append("roles", List.of(roleAdmin)), new Document("_id", "admin-3") - .append("userName", dotenv.get("ADMIN3_USERNAME")) - .append("password", passwordEncoder.encode(dotenv.get("ADMIN3_PASSWORD"))) + .append("userName", System.getenv("ADMIN3_USERNAME")) + .append("password", passwordEncoder.encode(System.getenv("ADMIN3_PASSWORD"))) .append("roles", List.of(roleAdmin)), new Document("_id", "admin-4") - .append("userName", dotenv.get("ADMIN4_USERNAME")) - .append("password", passwordEncoder.encode(dotenv.get("ADMIN4_PASSWORD"))) + .append("userName", System.getenv("ADMIN4_USERNAME")) + .append("password", passwordEncoder.encode(System.getenv("ADMIN4_PASSWORD"))) .append("roles", List.of(roleAdmin)) )); + System.out.println("Usuários criados com sucesso!"); } else { System.out.println("Usuários já existem no banco. Inicialização de usuários não necessária."); diff --git a/cadastral/src/main/resources/application-heroku.yml b/cadastral/src/main/resources/application-heroku.yml index c25b1ebf..a7c219cf 100644 --- a/cadastral/src/main/resources/application-heroku.yml +++ b/cadastral/src/main/resources/application-heroku.yml @@ -25,8 +25,9 @@ spring: enabled: false autoconfigure: - - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration - - org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration + exclude: + - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration + - org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration jmx: enabled: false @@ -44,3 +45,11 @@ eureka: enabled: false register-with-eureka: false fetch-registry: false + +ead: + auth: + jwtSecret: a7w!z%C*F-JaNdRgUkXp2s5v8x/A?D(G+KbPeShVmYq3t6w9z$B&E)H@McQfTjWs + jwtExpirationMs: 14400000 + +app: + uploads-dir: C:/Users/Samuel Modesto/OneDrive/Documentos/Projetos/TCC/imovato/backend/cadastral/uploads/ diff --git a/cadastral/src/main/resources/application.yml b/cadastral/src/main/resources/application.yml index cf9f19da..d63b3df5 100644 --- a/cadastral/src/main/resources/application.yml +++ b/cadastral/src/main/resources/application.yml @@ -2,7 +2,4 @@ spring: application: name: cadastral -ead: - auth: - jwtSecret: a7w!z%C*F-JaNdRgUkXp2s5v8x/A?D(G+KbPeShVmYq3t6w9z$B&E)H@McQfTjWs - jwtExpirationMs: 14400000 + From ed3bac517faa6ef3cfe31bb6e964036c4223bfc5 Mon Sep 17 00:00:00 2001 From: Samuel Modesto Date: Wed, 26 Nov 2025 14:38:12 -0300 Subject: [PATCH 03/15] alteracoes para subida no heroku --- cadastral/pom.xml | 7 +++ .../crud/config/CloudinaryConfig.java | 18 ++++++++ .../crud/resources/AccommodationResource.java | 3 ++ .../crud/resources/ImageResource.java | 28 ++++++++++++ .../unipampa/crud/resources/UserResource.java | 10 ++--- .../unipampa/crud/service/ImageService.java | 43 +++++++++++++++++++ .../impl/AccommodationServiceImpl.java | 28 ++++++++---- .../src/main/resources/application-heroku.yml | 4 +- .../rent/resources/BookingResource.java | 10 ++--- 9 files changed, 130 insertions(+), 21 deletions(-) create mode 100644 cadastral/src/main/java/com/unipampa/crud/config/CloudinaryConfig.java create mode 100644 cadastral/src/main/java/com/unipampa/crud/resources/ImageResource.java create mode 100644 cadastral/src/main/java/com/unipampa/crud/service/ImageService.java diff --git a/cadastral/pom.xml b/cadastral/pom.xml index 4afb8e09..bf30e24c 100644 --- a/cadastral/pom.xml +++ b/cadastral/pom.xml @@ -126,6 +126,13 @@ 1.5.5.Final + + com.cloudinary + cloudinary-http44 + 1.29.0 + + + diff --git a/cadastral/src/main/java/com/unipampa/crud/config/CloudinaryConfig.java b/cadastral/src/main/java/com/unipampa/crud/config/CloudinaryConfig.java new file mode 100644 index 00000000..9615c0b5 --- /dev/null +++ b/cadastral/src/main/java/com/unipampa/crud/config/CloudinaryConfig.java @@ -0,0 +1,18 @@ +package com.unipampa.crud.config; + +import com.cloudinary.Cloudinary; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class CloudinaryConfig { + + @Value("${CLOUDINARY_URL}") + private String cloudinaryUrl; + + @Bean + public Cloudinary cloudinary() { + return new Cloudinary(cloudinaryUrl); + } +} diff --git a/cadastral/src/main/java/com/unipampa/crud/resources/AccommodationResource.java b/cadastral/src/main/java/com/unipampa/crud/resources/AccommodationResource.java index e542830f..af5adbe0 100644 --- a/cadastral/src/main/java/com/unipampa/crud/resources/AccommodationResource.java +++ b/cadastral/src/main/java/com/unipampa/crud/resources/AccommodationResource.java @@ -80,12 +80,15 @@ public ResponseEntity save( AccommodationRequestDTO accommodationDTO = mapper.readValue(dadosJson, AccommodationRequestDTO.class); validations.forEach(e -> e.validate(accommodationDTO)); + var accommodation = accommodationMapper.toEntity(accommodationDTO); String novoId = new ObjectId().toString(); accommodation.setId(novoId); + String authenticatedUserId = SecurityUtil.getAuthenticatedUserId(); accommodation.setHostId(authenticatedUserId); accommodation.setStats(AccommodationStats.AVAILABLE); + accommodationService.save(accommodation, images); URI location = URI.create("/accommodations/" + accommodation.getId()); diff --git a/cadastral/src/main/java/com/unipampa/crud/resources/ImageResource.java b/cadastral/src/main/java/com/unipampa/crud/resources/ImageResource.java new file mode 100644 index 00000000..3d71485f --- /dev/null +++ b/cadastral/src/main/java/com/unipampa/crud/resources/ImageResource.java @@ -0,0 +1,28 @@ +package com.unipampa.crud.resources; + +import com.unipampa.crud.service.ImageService; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; + +@RestController +@RequestMapping("/images") +public class ImageResource { + + private final ImageService imageService; + + public ImageResource(ImageService imageService) { + this.imageService = imageService; + } + + @PostMapping + public ResponseEntity> upload(@RequestParam("files") List files) { + List urls = imageService.uploadImages(files); + return ResponseEntity.ok(urls); + } +} diff --git a/cadastral/src/main/java/com/unipampa/crud/resources/UserResource.java b/cadastral/src/main/java/com/unipampa/crud/resources/UserResource.java index ddcdf59e..a01e639b 100644 --- a/cadastral/src/main/java/com/unipampa/crud/resources/UserResource.java +++ b/cadastral/src/main/java/com/unipampa/crud/resources/UserResource.java @@ -81,7 +81,7 @@ public ResponseEntity saveUser(@RequestBody UserDTO userDto) { } - @PreAuthorize( "hasRole('ROLE_ADMINISTRATOR')" ) + @PreAuthorize( "hasRole('ADMINISTRATOR')" ) @GetMapping @Operation(summary = "Retorna todos os usuários cadastrados") public ResponseEntity> getAllUsers( @@ -93,7 +93,7 @@ public ResponseEntity> getAllUsers( return ResponseEntity.status(HttpStatus.OK).body(users); } - @PreAuthorize( "hasAnyRole('ROLE_ADMINISTRATOR', 'ROLE_HOST', 'ROLE_GUEST')" ) + @PreAuthorize( "hasAnyRole('ADMINISTRATOR', 'HOST', 'GUEST')" ) @GetMapping("email/{email}") @Operation(summary = "Retorna um usuario pelo email") public ResponseEntity getUserByEmail(@PathVariable("email") String email) { @@ -105,7 +105,7 @@ public ResponseEntity getUserByEmail(@PathVariable("email") String email return new ResponseEntity<>(user, HttpStatus.OK); } - @PreAuthorize( "hasAnyRole('ROLE_ADMINISTRATOR', 'ROLE_HOST', 'ROLE_GUEST')" ) + @PreAuthorize( "hasAnyRole('ADMINISTRATOR', 'HOST', 'GUEST')" ) @GetMapping("{id}") @Operation(summary = "Retorna um usuario pelo id") public ResponseEntity getUserById(@PathVariable("id") String id) { @@ -117,7 +117,7 @@ public ResponseEntity getUserById(@PathVariable("id") String id) { return new ResponseEntity<>(user, HttpStatus.OK); } - @PreAuthorize( "hasAnyRole('ROLE_ADMINISTRATOR', 'ROLE_HOST', 'ROLE_GUEST')" ) + @PreAuthorize( "hasAnyRole('ADMINISTRATOR', 'HOST', 'GUEST')" ) @PutMapping("{id}") @Operation(summary = "Atualiza um usuario pelo id") public ResponseEntity updateUser(@RequestBody UserDTO userDTO, @PathVariable("id")String id) { @@ -132,7 +132,7 @@ public ResponseEntity updateUser(@RequestBody UserDTO userDTO, @PathVar return new ResponseEntity<>(userModel, HttpStatus.OK); } - @PreAuthorize( "hasAnyRole('ROLE_ADMINISTRATOR', 'ROLE_HOST', 'ROLE_GUEST')" ) + @PreAuthorize( "hasAnyRole('ADMINISTRATOR', 'HOST', 'GUEST')" ) @DeleteMapping("{id}") @Operation(summary = "Remove um usuario pelo seu id") public ResponseEntity deleteUser(@PathVariable("id") String id) { diff --git a/cadastral/src/main/java/com/unipampa/crud/service/ImageService.java b/cadastral/src/main/java/com/unipampa/crud/service/ImageService.java new file mode 100644 index 00000000..57195cf9 --- /dev/null +++ b/cadastral/src/main/java/com/unipampa/crud/service/ImageService.java @@ -0,0 +1,43 @@ +package com.unipampa.crud.service; + +import com.cloudinary.Cloudinary; +import com.cloudinary.utils.ObjectUtils; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +@Service +public class ImageService { + + private final Cloudinary cloudinary; + + public ImageService(Cloudinary cloudinary) { + this.cloudinary = cloudinary; + } + + public List uploadImages(List files) { + if (files == null || files.isEmpty()) { + throw new IllegalArgumentException("Envie ao menos uma imagem."); + } + + List urls = new ArrayList<>(); + + for (MultipartFile file : files) { + try { + Map result = cloudinary.uploader().upload( + file.getBytes(), + ObjectUtils.asMap("folder", "imovato/accommodations") + ); + urls.add(result.get("secure_url").toString()); + + } catch (Exception e) { + throw new RuntimeException("Erro ao fazer upload para Cloudinary", e); + } + } + + return urls; + } +} diff --git a/cadastral/src/main/java/com/unipampa/crud/service/impl/AccommodationServiceImpl.java b/cadastral/src/main/java/com/unipampa/crud/service/impl/AccommodationServiceImpl.java index 63b7d735..3b97814e 100644 --- a/cadastral/src/main/java/com/unipampa/crud/service/impl/AccommodationServiceImpl.java +++ b/cadastral/src/main/java/com/unipampa/crud/service/impl/AccommodationServiceImpl.java @@ -6,6 +6,7 @@ import com.unipampa.crud.repository.AccommodationRepository; import com.unipampa.crud.sender.AccommodationSender; import com.unipampa.crud.service.AccommodationService; +import com.unipampa.crud.service.ImageService; import jakarta.persistence.EntityNotFoundException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -19,10 +20,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.UUID; +import java.util.*; @Service public class AccommodationServiceImpl implements AccommodationService { @@ -35,22 +33,34 @@ public class AccommodationServiceImpl implements AccommodationService { public static final String TAMANHO_MAXIMO_DA_IMAGEM = "Imagem excede o tamanho máximo permitido de 5MB."; private AccommodationRepository propertyRepository; private AccommodationSender accommodationSender; + private ImageService imageService; @Value("${app.uploads-dir}") private String uploadsDir; @Autowired - public AccommodationServiceImpl(AccommodationRepository repository, AccommodationSender sendMessage) { + public AccommodationServiceImpl(AccommodationRepository repository, AccommodationSender sendMessage, ImageService imageService) { this.propertyRepository = repository; this.accommodationSender = sendMessage; + this.imageService = imageService; } @Override @Transactional - public void save(Accommodation hosting, MultipartFile[] images) throws IOException { - List caminhos = buildPathForImages(hosting.getId(), images); - hosting.setImagesUrls(caminhos); - Accommodation savedWithImages = propertyRepository.save(hosting); + public void save(Accommodation accommodation, MultipartFile[] images) throws IOException { + + List urls = new ArrayList<>(); + + if (images != null && images.length > 0) { + List files = Arrays.asList(images); + List uploadedUrls = imageService.uploadImages(files); + urls.addAll(uploadedUrls); + + } + + accommodation.setImagesUrls(urls); + + Accommodation savedWithImages = propertyRepository.save(accommodation); accommodationSender.sendMessage(savedWithImages); } diff --git a/cadastral/src/main/resources/application-heroku.yml b/cadastral/src/main/resources/application-heroku.yml index a7c219cf..9b03df31 100644 --- a/cadastral/src/main/resources/application-heroku.yml +++ b/cadastral/src/main/resources/application-heroku.yml @@ -19,7 +19,7 @@ spring: uri: ${MONGODB_URI} rabbitmq: - uri: ${CLOUDAMQP_URL} + addresses: ${CLOUDAMQP_URL} jpa: enabled: false @@ -48,7 +48,7 @@ eureka: ead: auth: - jwtSecret: a7w!z%C*F-JaNdRgUkXp2s5v8x/A?D(G+KbPeShVmYq3t6w9z$B&E)H@McQfTjWs + jwtSecret: ${AUTH_JWTSECRET} jwtExpirationMs: 14400000 app: diff --git a/transacional/src/main/java/com/example/rent/resources/BookingResource.java b/transacional/src/main/java/com/example/rent/resources/BookingResource.java index eb8699a6..ecbfedb0 100644 --- a/transacional/src/main/java/com/example/rent/resources/BookingResource.java +++ b/transacional/src/main/java/com/example/rent/resources/BookingResource.java @@ -41,7 +41,7 @@ public class BookingResource { - @PreAuthorize("hasAnyRole('ROLE_ADMINISTRATOR', 'ROLE_GUEST')") + @PreAuthorize("hasAnyRole('ROLE_ADMINISTRATOR', 'GUEST')") @PostMapping @Operation(summary = "Cria uma reserva para uma propriedade existente") public ResponseEntity createBooking(@RequestBody BookingDto request, Authentication authentication) { @@ -49,14 +49,14 @@ public ResponseEntity createBooking(@RequestBody BookingDto request, Au return ResponseEntity.status(HttpStatus.CREATED).body(response); } - @PreAuthorize("hasAnyRole('ROLE_ADMINISTRATOR', 'ROLE_GUEST')") + @PreAuthorize("hasAnyRole('ROLE_ADMINISTRATOR', 'GUEST')") @PostMapping("/checkin/{idBooking}") @Operation(summary = "Faz checkin em uma reserva existente") public ResponseEntity checkin(@PathVariable @Valid Long idBooking) { return new ResponseEntity<>(rentService.processCheckin(idBooking), HttpStatus.CREATED); } - @PreAuthorize("hasAnyRole('ROLE_ADMINISTRATOR', 'ROLE_GUEST', 'ROLE_HOST')") + @PreAuthorize("hasAnyRole('ROLE_ADMINISTRATOR', 'GUEST', 'ROLE_HOST')") @Operation(summary = "Consulta uma reserva existente") @GetMapping("/{id}") public ResponseEntity getBookingById(@PathVariable Long id) throws Exception { @@ -65,7 +65,7 @@ public ResponseEntity getBookingById(@PathVariable Long id) throws E return ResponseEntity.ok(BookingMapper.toDto(booking)); } - @PreAuthorize("hasAnyRole('ROLE_ADMINISTRATOR', 'ROLE_GUEST', 'ROLE_HOST')") + @PreAuthorize("hasAnyRole('ROLE_ADMINISTRATOR', 'GUEST', 'ROLE_HOST')") @Operation(summary = "Cancela uma reserva existente") @PatchMapping("/{id}/cancel") public ResponseEntity cancelBookingById(@PathVariable Long id) throws Exception { @@ -73,7 +73,7 @@ public ResponseEntity cancelBookingById(@PathVariable Long id) throw return ResponseEntity.ok(BookingMapper.toDto(booking)); } - @PreAuthorize("hasAnyRole('ROLE_ADMINISTRATOR', 'ROLE_GUEST')") + @PreAuthorize("hasAnyRole('ROLE_ADMINISTRATOR', 'GUEST')") @PatchMapping("/{id}/pay/{userId}") @Operation(summary = "Realiza o pagamento de uma reserva") public ResponseEntity payBooking(@PathVariable Long id, @PathVariable String userId) throws Exception { From f91883694808533a842a11bcd81606b3fc978482 Mon Sep 17 00:00:00 2001 From: Samuel Modesto Date: Sat, 27 Dec 2025 11:33:25 -0300 Subject: [PATCH 04/15] correcao para retornar urls do cloudnary --- .../crud/mappers/AccommodationMapper.java | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/cadastral/src/main/java/com/unipampa/crud/mappers/AccommodationMapper.java b/cadastral/src/main/java/com/unipampa/crud/mappers/AccommodationMapper.java index df904d48..e42a4251 100644 --- a/cadastral/src/main/java/com/unipampa/crud/mappers/AccommodationMapper.java +++ b/cadastral/src/main/java/com/unipampa/crud/mappers/AccommodationMapper.java @@ -36,15 +36,8 @@ public Accommodation toEntity(AccommodationRequestDTO requestDTO) { } public AccommodationDTO toDTO(Accommodation entity) { - String urlBase = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort(); - List imageUrls = entity.getImagesUrls().stream() - .map(path -> { - Path p = Paths.get(path); - String id = p.getParent().getFileName().toString(); // exemplo: "6804eaef24e9aa24141421a1" - String filename = p.getFileName().toString(); - return urlBase + "/accommodations/images/" + id + "/" + filename; - }) - .collect(Collectors.toList()); + + List imageUrls = entity.getImagesUrls(); return new AccommodationDTO( entity.getId(), @@ -57,12 +50,11 @@ public AccommodationDTO toDTO(Accommodation entity) { entity.getState(), entity.getPrice(), entity.getStreetNumber(), - entity.getImagesUrls() != null ? entity.getImagesUrls().size() : 0, + imageUrls != null ? imageUrls.size() : 0, entity.getType(), entity.getMaxOccupancy(), imageUrls ); - - } + } From dc6141ffe474e2f65bb94ded10b778b02897fffa Mon Sep 17 00:00:00 2001 From: Samuel Modesto Date: Sat, 27 Dec 2025 15:15:46 -0300 Subject: [PATCH 05/15] correcao para retornar campos do banco de dados que nao estavam sendo retornados (numero de quartos, isCompartilhado, pet friendly) --- .../unipampa/crud/dto/AccommodationDTO.java | 25 ++++++++++++++----- .../crud/dto/AccommodationRequestDTO.java | 22 +++++++++++++--- .../crud/mappers/AccommodationMapper.java | 5 +++- .../crud/resources/AccommodationResource.java | 12 +++++++++ .../resources/AccommodationResourceTest.java | 4 +++ .../ValidateAccommodationRegisteredTest.java | 4 +++ 6 files changed, 62 insertions(+), 10 deletions(-) diff --git a/cadastral/src/main/java/com/unipampa/crud/dto/AccommodationDTO.java b/cadastral/src/main/java/com/unipampa/crud/dto/AccommodationDTO.java index a4056e1f..aeb229c6 100644 --- a/cadastral/src/main/java/com/unipampa/crud/dto/AccommodationDTO.java +++ b/cadastral/src/main/java/com/unipampa/crud/dto/AccommodationDTO.java @@ -9,11 +9,8 @@ import java.util.List; public record AccommodationDTO( - @Schema(example = "6804eaef24e9aa24141421a1") - String id, - @NotBlank - @Schema(example = "Apartamento moderno no centro") + @Schema(example = "Apartamento moderno no centro 2") String title, @Schema(example = "Centro Histórico") @@ -27,7 +24,7 @@ public record AccommodationDTO( String city, @NotBlank - @Schema(example = "Apartamento bem iluminado, com 2 quartos e cozinha equipada.") + @Schema(example = "Apartamento bem iluminado, com 3 quartos e cozinha equipada.") String description, @Schema(example = "Rua dos Andradas") @@ -56,6 +53,22 @@ public record AccommodationDTO( @Schema(example = "4") Integer maxOccupancy, - @Schema(example = "[\"https://img.com/1.jpg\", \"https://img.com/2.jpg\"]") + @NotNull + @Schema(example = "2") + Integer roomCount, + + @NotNull + @Schema(example = "1") + Integer bathroomCount, + + @NotNull + @Schema(example = "true") + Boolean allowsPets, + + @NotNull + @Schema(example = "true") + Boolean isSharedHosting, + + @Schema(example = "[]") List imagesUrls ) {} diff --git a/cadastral/src/main/java/com/unipampa/crud/dto/AccommodationRequestDTO.java b/cadastral/src/main/java/com/unipampa/crud/dto/AccommodationRequestDTO.java index 281ec649..26f412f1 100644 --- a/cadastral/src/main/java/com/unipampa/crud/dto/AccommodationRequestDTO.java +++ b/cadastral/src/main/java/com/unipampa/crud/dto/AccommodationRequestDTO.java @@ -10,7 +10,7 @@ public record AccommodationRequestDTO( @NotBlank - @Schema(example = "Apartamento moderno no centro") + @Schema(example = "Apartamento moderno no centro 2") String title, @Schema(example = "Centro Histórico") @@ -24,7 +24,7 @@ public record AccommodationRequestDTO( String city, @NotBlank - @Schema(example = "Apartamento bem iluminado, com 2 quartos e cozinha equipada.") + @Schema(example = "Apartamento bem iluminado, com 3 quartos e cozinha equipada.") String description, @Schema(example = "Rua dos Andradas") @@ -53,7 +53,23 @@ public record AccommodationRequestDTO( @Schema(example = "4") Integer maxOccupancy, - @Schema(example = "[\"https://img.com/1.jpg\", \"https://img.com/2.jpg\"]") + @NotNull + @Schema(example = "2") + Integer roomCount, + + @NotNull + @Schema(example = "1") + Integer bathroomCount, + + @NotNull + @Schema(example = "true") + Boolean allowsPets, + + @NotNull + @Schema(example = "true") + Boolean isSharedHosting, + + @Schema(example = "[]") List imagesUrls, @NotBlank diff --git a/cadastral/src/main/java/com/unipampa/crud/mappers/AccommodationMapper.java b/cadastral/src/main/java/com/unipampa/crud/mappers/AccommodationMapper.java index e42a4251..c571ef98 100644 --- a/cadastral/src/main/java/com/unipampa/crud/mappers/AccommodationMapper.java +++ b/cadastral/src/main/java/com/unipampa/crud/mappers/AccommodationMapper.java @@ -40,7 +40,6 @@ public AccommodationDTO toDTO(Accommodation entity) { List imageUrls = entity.getImagesUrls(); return new AccommodationDTO( - entity.getId(), entity.getTitle(), entity.getNeighborhood(), entity.getZipCode(), @@ -53,6 +52,10 @@ public AccommodationDTO toDTO(Accommodation entity) { imageUrls != null ? imageUrls.size() : 0, entity.getType(), entity.getMaxOccupancy(), + entity.getRoomCount(), + entity.getBathroomCount(), + entity.isAllowsPets(), + entity.isSharedHosting(), imageUrls ); } diff --git a/cadastral/src/main/java/com/unipampa/crud/resources/AccommodationResource.java b/cadastral/src/main/java/com/unipampa/crud/resources/AccommodationResource.java index af5adbe0..eb9b3767 100644 --- a/cadastral/src/main/java/com/unipampa/crud/resources/AccommodationResource.java +++ b/cadastral/src/main/java/com/unipampa/crud/resources/AccommodationResource.java @@ -149,6 +149,18 @@ public ResponseEntity updateAccommodation( accommodation.setTitle(accommodationDTO.title()); accommodation.setAddress(accommodationDTO.address()); accommodation.setPrice(accommodationDTO.price()); + accommodation.setDescription(accommodationDTO.description()); + accommodation.setCity(accommodationDTO.city()); + accommodation.setNeighborhood(accommodationDTO.neighborhood()); + accommodation.setState(accommodationDTO.state()); + accommodation.setZipCode(accommodationDTO.codAddress()); + accommodation.setStreetNumber(accommodationDTO.streetNumber()); + accommodation.setType(accommodationDTO.accommodationType()); + accommodation.setMaxOccupancy(accommodationDTO.maxOccupancy()); + accommodation.setRoomCount(accommodationDTO.roomCount()); + accommodation.setBathroomCount(accommodationDTO.bathroomCount()); + accommodation.setAllowsPets(accommodationDTO.allowsPets()); + accommodation.setSharedHosting(accommodationDTO.isSharedHosting()); try { accommodationService.save(accommodation, images); diff --git a/cadastral/src/test/java/com/unipampa/crud/resources/AccommodationResourceTest.java b/cadastral/src/test/java/com/unipampa/crud/resources/AccommodationResourceTest.java index 9c7b18e0..a33ed0cf 100644 --- a/cadastral/src/test/java/com/unipampa/crud/resources/AccommodationResourceTest.java +++ b/cadastral/src/test/java/com/unipampa/crud/resources/AccommodationResourceTest.java @@ -62,6 +62,10 @@ void setUp() { 5, AccommodationType.APARTMENT, 5, + 2, + 1, + true, + false, List.of("https://img.com/1.jpg", "https://img.com/2.jpg"), "123345" ); diff --git a/cadastral/src/test/java/com/unipampa/crud/validations/impl/ValidateAccommodationRegisteredTest.java b/cadastral/src/test/java/com/unipampa/crud/validations/impl/ValidateAccommodationRegisteredTest.java index 7e0ad267..1542ccb2 100644 --- a/cadastral/src/test/java/com/unipampa/crud/validations/impl/ValidateAccommodationRegisteredTest.java +++ b/cadastral/src/test/java/com/unipampa/crud/validations/impl/ValidateAccommodationRegisteredTest.java @@ -44,6 +44,10 @@ void setUp() { 5, AccommodationType.HOUSE, 5, + 3, + 2, + true, + false, List.of("https://img.com/1.jpg", "https://img.com/2.jpg"), "12345" ); From ef9042e736acccad6f6e6ee44056dee07cdd08a2 Mon Sep 17 00:00:00 2001 From: Samuel Modesto Date: Sat, 27 Dec 2025 16:07:30 -0300 Subject: [PATCH 06/15] ajuste no dto para salvar usuario --- .../java/com/unipampa/crud/dto/UserDTO.java | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/cadastral/src/main/java/com/unipampa/crud/dto/UserDTO.java b/cadastral/src/main/java/com/unipampa/crud/dto/UserDTO.java index 3a6af92f..edc87ac6 100644 --- a/cadastral/src/main/java/com/unipampa/crud/dto/UserDTO.java +++ b/cadastral/src/main/java/com/unipampa/crud/dto/UserDTO.java @@ -5,13 +5,14 @@ import jakarta.validation.constraints.NotBlank; public record UserDTO( - @NotBlank String email, - @NotBlank String name, - @NotBlank String userName, - @NotBlank String cpf, - @NotBlank String phone, - @NotBlank String address, - @NotBlank String password, - @NotBlank String role, - @NotBlank UserType type -) {} \ No newline at end of file + @NotBlank String email, + @NotBlank String name, + @NotBlank String userName, + @NotBlank String cpf, + @NotBlank String password, + @NotBlank String role, + @NotBlank UserType type, + String phone, + String address +) { +} \ No newline at end of file From d4478e18a706e2622403a40cf36ca630e1f83586 Mon Sep 17 00:00:00 2001 From: Samuel Modesto Date: Sat, 27 Dec 2025 16:32:38 -0300 Subject: [PATCH 07/15] adicionando email nos administradores --- .../com/unipampa/crud/config/MongoScriptInitializer.java | 4 ++++ cadastral/src/main/resources/.env | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/cadastral/src/main/java/com/unipampa/crud/config/MongoScriptInitializer.java b/cadastral/src/main/java/com/unipampa/crud/config/MongoScriptInitializer.java index 47e7ef3b..192786eb 100644 --- a/cadastral/src/main/java/com/unipampa/crud/config/MongoScriptInitializer.java +++ b/cadastral/src/main/java/com/unipampa/crud/config/MongoScriptInitializer.java @@ -67,21 +67,25 @@ public void run(String... args) throws Exception { new Document("_id", "admin-1") .append("userName", System.getenv("ADMIN1_USERNAME")) .append("password", passwordEncoder.encode(System.getenv("ADMIN1_PASSWORD"))) + .append("email", System.getenv("ADMIN1_EMAIL")) .append("roles", List.of(roleAdmin)), new Document("_id", "admin-2") .append("userName", System.getenv("ADMIN2_USERNAME")) .append("password", passwordEncoder.encode(System.getenv("ADMIN2_PASSWORD"))) + .append("email", System.getenv("ADMIN2_EMAIL")) .append("roles", List.of(roleAdmin)), new Document("_id", "admin-3") .append("userName", System.getenv("ADMIN3_USERNAME")) .append("password", passwordEncoder.encode(System.getenv("ADMIN3_PASSWORD"))) + .append("email", System.getenv("ADMIN3_EMAIL")) .append("roles", List.of(roleAdmin)), new Document("_id", "admin-4") .append("userName", System.getenv("ADMIN4_USERNAME")) .append("password", passwordEncoder.encode(System.getenv("ADMIN4_PASSWORD"))) + .append("email", System.getenv("ADMIN4_EMAIL")) .append("roles", List.of(roleAdmin)) )); diff --git a/cadastral/src/main/resources/.env b/cadastral/src/main/resources/.env index 844d3663..418332e2 100644 --- a/cadastral/src/main/resources/.env +++ b/cadastral/src/main/resources/.env @@ -1,12 +1,17 @@ # Variáveis relacionadas ao MongoDB ADMIN1_USERNAME=samuel ADMIN1_PASSWORD=123456 +ADMIN1_EMAIL=samuel@email.com ADMIN2_USERNAME=denner ADMIN2_PASSWORD=123456 +ADMIN2_EMAIL=denner@email.com ADMIN3_USERNAME=basso ADMIN3_PASSWORD=123456 +ADMIN3_EMAIL=basso@email.com ADMIN4_USERNAME=auri ADMIN4_PASSWORD=123456 +ADMIN4_EMAIL=auri@email.com + From 4c79bc4ea0a74a99e0b975a2c26ffd030a7c26bb Mon Sep 17 00:00:00 2001 From: Samuel Modesto Date: Sat, 27 Dec 2025 16:34:44 -0300 Subject: [PATCH 08/15] Revert "heroku config" This reverts commit 84cc445efd77d2baa31544869ad328b874aae66e. --- discovery/Dockerfile | 23 --------- discovery/pom.xml | 18 ------- .../discovery/config/SecurityConfig.java | 40 ++++++++++++++-- .../src/main/resources/application-heroku.yml | 16 ------- discovery/src/main/resources/application.yml | 2 + gateway/Dockerfile | 19 -------- gateway/pom.xml | 47 +++++++++---------- .../src/main/resources/application-heroku.yml | 20 -------- gateway/src/main/resources/application.yml | 6 +++ 9 files changed, 64 insertions(+), 127 deletions(-) delete mode 100644 discovery/Dockerfile delete mode 100644 discovery/src/main/resources/application-heroku.yml delete mode 100644 gateway/Dockerfile delete mode 100644 gateway/src/main/resources/application-heroku.yml diff --git a/discovery/Dockerfile b/discovery/Dockerfile deleted file mode 100644 index 8de47b92..00000000 --- a/discovery/Dockerfile +++ /dev/null @@ -1,23 +0,0 @@ -# ---------- stage 1: build ---------- -FROM maven:3.9.6-eclipse-temurin-21 AS build - -WORKDIR /app - -COPY pom.xml . -RUN mvn -q -e -DskipTests dependency:go-offline - -COPY . . -RUN mvn clean package -DskipTests - - -# ---------- stage 2: runtime ---------- -FROM eclipse-temurin:21-jre AS runtime - -WORKDIR /app - -COPY --from=build /app/target/*.jar app.jar - -# Heroku ignora EXPOSE, mas é bom manter para documentação -EXPOSE 8080 - -CMD ["sh", "-c", "java -Dserver.port=$PORT -jar app.jar"] diff --git a/discovery/pom.xml b/discovery/pom.xml index 92895c40..73a48586 100644 --- a/discovery/pom.xml +++ b/discovery/pom.xml @@ -58,22 +58,4 @@ - - - - - org.springframework.boot - spring-boot-maven-plugin - 3.4.2 - - - - repackage - - - - - - - diff --git a/discovery/src/main/java/com/example/discovery/config/SecurityConfig.java b/discovery/src/main/java/com/example/discovery/config/SecurityConfig.java index 6c4450f8..76078e8a 100644 --- a/discovery/src/main/java/com/example/discovery/config/SecurityConfig.java +++ b/discovery/src/main/java/com/example/discovery/config/SecurityConfig.java @@ -2,17 +2,47 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.Customizer; +import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.provisioning.InMemoryUserDetailsManager; import org.springframework.security.web.SecurityFilterChain; @Configuration +@EnableMethodSecurity public class SecurityConfig { @Bean - public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { - http - .csrf(csrf -> csrf.disable()) - .authorizeHttpRequests(auth -> auth.anyRequest().permitAll()); + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + http.authorizeHttpRequests(auth -> auth + .requestMatchers("/eureka/**").permitAll() + .requestMatchers("/actuator/**").permitAll() + .anyRequest().authenticated() + ) + .httpBasic(Customizer.withDefaults()) + .csrf(AbstractHttpConfigurer::disable); return http.build(); } -} + + @Bean + public UserDetailsService userDetailsService(PasswordEncoder encoder) { + UserDetails user = User.builder() + .username("un_user") + .password(encoder.encode("un_user")) + .roles("ADMIN") + .build(); + + return new InMemoryUserDetailsManager(user); + } + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } +} \ No newline at end of file diff --git a/discovery/src/main/resources/application-heroku.yml b/discovery/src/main/resources/application-heroku.yml deleted file mode 100644 index 4ab33d9a..00000000 --- a/discovery/src/main/resources/application-heroku.yml +++ /dev/null @@ -1,16 +0,0 @@ -spring: - config: - activate: - on-profile: heroku - application: - name: discovery - -server: - port: ${PORT:8080} - -eureka: - client: - register-with-eureka: false - fetch-registry: false - server: - enable-self-preservation: false diff --git a/discovery/src/main/resources/application.yml b/discovery/src/main/resources/application.yml index 113605a6..ff55f658 100644 --- a/discovery/src/main/resources/application.yml +++ b/discovery/src/main/resources/application.yml @@ -1,3 +1,5 @@ spring: application: name: discovery + profiles: + active: dev diff --git a/gateway/Dockerfile b/gateway/Dockerfile deleted file mode 100644 index 0e2e8117..00000000 --- a/gateway/Dockerfile +++ /dev/null @@ -1,19 +0,0 @@ -FROM maven:3.9.6-eclipse-temurin-21 AS build - -WORKDIR /app - -COPY pom.xml . -RUN mvn -q -e -DskipTests dependency:go-offline - -COPY . . -RUN mvn clean package -DskipTests - -FROM eclipse-temurin:21-jre AS runtime - -WORKDIR /app - -COPY --from=build /app/target/*.jar app.jar - -EXPOSE 8080 - -CMD ["sh", "-c", "java -Dserver.port=$PORT -jar app.jar"] diff --git a/gateway/pom.xml b/gateway/pom.xml index 0ccafcbf..7eaa9f0e 100644 --- a/gateway/pom.xml +++ b/gateway/pom.xml @@ -1,58 +1,60 @@ - - + 4.0.0 - org.springframework.boot spring-boot-starter-parent 3.4.2 - + - com.imovato gateway 0.0.1-SNAPSHOT gateway - + Demo project for Spring Boot + + + + + + + + + + + + + 21 2024.0.0 - - org.springframework.cloud spring-cloud-starter-gateway - org.springframework.cloud spring-cloud-starter-netflix-eureka-client - - org.springframework.boot - spring-boot-starter-actuator - - org.springframework.boot spring-boot-starter-test test - io.projectreactor reactor-test test - + + org.springframework.cloud + spring-cloud-starter-config + - @@ -70,13 +72,6 @@ org.springframework.boot spring-boot-maven-plugin - - - - repackage - - - diff --git a/gateway/src/main/resources/application-heroku.yml b/gateway/src/main/resources/application-heroku.yml deleted file mode 100644 index 6e700271..00000000 --- a/gateway/src/main/resources/application-heroku.yml +++ /dev/null @@ -1,20 +0,0 @@ -server: - port: ${PORT:8080} - -spring: - application: - name: gateway - - cloud: - gateway: - discovery: - locator: - enabled: true - lower-case-service-id: true - -eureka: - client: - registerWithEureka: true - fetchRegistry: true - service-url: - defaultZone: "http://${EUREKA_HOST}/eureka/" diff --git a/gateway/src/main/resources/application.yml b/gateway/src/main/resources/application.yml index 3eec156d..c65d5a22 100644 --- a/gateway/src/main/resources/application.yml +++ b/gateway/src/main/resources/application.yml @@ -1,3 +1,9 @@ spring: application: name: gateway + config: + import: "configserver:" + cloud: + config: + discovery: + service-id: config-server \ No newline at end of file From c911584bdbd84ae6faad7723c2310223210cb85c Mon Sep 17 00:00:00 2001 From: Samuel Modesto Date: Sat, 27 Dec 2025 16:35:28 -0300 Subject: [PATCH 09/15] Revert "adicionando email nos administradores" This reverts commit d4478e18a706e2622403a40cf36ca630e1f83586. --- .../com/unipampa/crud/config/MongoScriptInitializer.java | 4 ---- cadastral/src/main/resources/.env | 5 ----- 2 files changed, 9 deletions(-) diff --git a/cadastral/src/main/java/com/unipampa/crud/config/MongoScriptInitializer.java b/cadastral/src/main/java/com/unipampa/crud/config/MongoScriptInitializer.java index 192786eb..47e7ef3b 100644 --- a/cadastral/src/main/java/com/unipampa/crud/config/MongoScriptInitializer.java +++ b/cadastral/src/main/java/com/unipampa/crud/config/MongoScriptInitializer.java @@ -67,25 +67,21 @@ public void run(String... args) throws Exception { new Document("_id", "admin-1") .append("userName", System.getenv("ADMIN1_USERNAME")) .append("password", passwordEncoder.encode(System.getenv("ADMIN1_PASSWORD"))) - .append("email", System.getenv("ADMIN1_EMAIL")) .append("roles", List.of(roleAdmin)), new Document("_id", "admin-2") .append("userName", System.getenv("ADMIN2_USERNAME")) .append("password", passwordEncoder.encode(System.getenv("ADMIN2_PASSWORD"))) - .append("email", System.getenv("ADMIN2_EMAIL")) .append("roles", List.of(roleAdmin)), new Document("_id", "admin-3") .append("userName", System.getenv("ADMIN3_USERNAME")) .append("password", passwordEncoder.encode(System.getenv("ADMIN3_PASSWORD"))) - .append("email", System.getenv("ADMIN3_EMAIL")) .append("roles", List.of(roleAdmin)), new Document("_id", "admin-4") .append("userName", System.getenv("ADMIN4_USERNAME")) .append("password", passwordEncoder.encode(System.getenv("ADMIN4_PASSWORD"))) - .append("email", System.getenv("ADMIN4_EMAIL")) .append("roles", List.of(roleAdmin)) )); diff --git a/cadastral/src/main/resources/.env b/cadastral/src/main/resources/.env index 418332e2..844d3663 100644 --- a/cadastral/src/main/resources/.env +++ b/cadastral/src/main/resources/.env @@ -1,17 +1,12 @@ # Variáveis relacionadas ao MongoDB ADMIN1_USERNAME=samuel ADMIN1_PASSWORD=123456 -ADMIN1_EMAIL=samuel@email.com ADMIN2_USERNAME=denner ADMIN2_PASSWORD=123456 -ADMIN2_EMAIL=denner@email.com ADMIN3_USERNAME=basso ADMIN3_PASSWORD=123456 -ADMIN3_EMAIL=basso@email.com ADMIN4_USERNAME=auri ADMIN4_PASSWORD=123456 -ADMIN4_EMAIL=auri@email.com - From 4a5dbb3c5cb1bbff5fb22c1b569e46dc850e81e0 Mon Sep 17 00:00:00 2001 From: Samuel Modesto Date: Sat, 27 Dec 2025 16:39:55 -0300 Subject: [PATCH 10/15] adicionando email nos administradores --- .../com/unipampa/crud/config/MongoScriptInitializer.java | 4 ++++ cadastral/src/main/resources/.env | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/cadastral/src/main/java/com/unipampa/crud/config/MongoScriptInitializer.java b/cadastral/src/main/java/com/unipampa/crud/config/MongoScriptInitializer.java index 47e7ef3b..192786eb 100644 --- a/cadastral/src/main/java/com/unipampa/crud/config/MongoScriptInitializer.java +++ b/cadastral/src/main/java/com/unipampa/crud/config/MongoScriptInitializer.java @@ -67,21 +67,25 @@ public void run(String... args) throws Exception { new Document("_id", "admin-1") .append("userName", System.getenv("ADMIN1_USERNAME")) .append("password", passwordEncoder.encode(System.getenv("ADMIN1_PASSWORD"))) + .append("email", System.getenv("ADMIN1_EMAIL")) .append("roles", List.of(roleAdmin)), new Document("_id", "admin-2") .append("userName", System.getenv("ADMIN2_USERNAME")) .append("password", passwordEncoder.encode(System.getenv("ADMIN2_PASSWORD"))) + .append("email", System.getenv("ADMIN2_EMAIL")) .append("roles", List.of(roleAdmin)), new Document("_id", "admin-3") .append("userName", System.getenv("ADMIN3_USERNAME")) .append("password", passwordEncoder.encode(System.getenv("ADMIN3_PASSWORD"))) + .append("email", System.getenv("ADMIN3_EMAIL")) .append("roles", List.of(roleAdmin)), new Document("_id", "admin-4") .append("userName", System.getenv("ADMIN4_USERNAME")) .append("password", passwordEncoder.encode(System.getenv("ADMIN4_PASSWORD"))) + .append("email", System.getenv("ADMIN4_EMAIL")) .append("roles", List.of(roleAdmin)) )); diff --git a/cadastral/src/main/resources/.env b/cadastral/src/main/resources/.env index 844d3663..418332e2 100644 --- a/cadastral/src/main/resources/.env +++ b/cadastral/src/main/resources/.env @@ -1,12 +1,17 @@ # Variáveis relacionadas ao MongoDB ADMIN1_USERNAME=samuel ADMIN1_PASSWORD=123456 +ADMIN1_EMAIL=samuel@email.com ADMIN2_USERNAME=denner ADMIN2_PASSWORD=123456 +ADMIN2_EMAIL=denner@email.com ADMIN3_USERNAME=basso ADMIN3_PASSWORD=123456 +ADMIN3_EMAIL=basso@email.com ADMIN4_USERNAME=auri ADMIN4_PASSWORD=123456 +ADMIN4_EMAIL=auri@email.com + From 762b8f4753d8b2f4eb227272b1d49117cb90b3b7 Mon Sep 17 00:00:00 2001 From: Samuel Modesto Date: Sat, 27 Dec 2025 17:00:10 -0300 Subject: [PATCH 11/15] corrigindo teste unitario --- .../java/com/unipampa/crud/resources/UserResourceTest.java | 6 +++--- .../java/com/unipampa/crud/validations/ValidateCpfTest.java | 6 +++--- .../com/unipampa/crud/validations/ValidateEmailTest.java | 6 +++--- .../com/unipampa/crud/validations/ValidateUserNameTest.java | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/cadastral/src/test/java/com/unipampa/crud/resources/UserResourceTest.java b/cadastral/src/test/java/com/unipampa/crud/resources/UserResourceTest.java index 112567e9..eaa6b750 100644 --- a/cadastral/src/test/java/com/unipampa/crud/resources/UserResourceTest.java +++ b/cadastral/src/test/java/com/unipampa/crud/resources/UserResourceTest.java @@ -61,11 +61,11 @@ void setUp() { "Cooper", "johnSnow", "123.456.789-00", - "(11) 99999-9999", - "123 Main St, Springfield", "123456", "ADMIN", - UserType.ROLE_ADMINISTRATOR + UserType.ROLE_ADMINISTRATOR, + "(11) 99999-9999", + "123 Main St, Springfield" ); user = User.builder() diff --git a/cadastral/src/test/java/com/unipampa/crud/validations/ValidateCpfTest.java b/cadastral/src/test/java/com/unipampa/crud/validations/ValidateCpfTest.java index 6992a6e5..7e3dcf3d 100644 --- a/cadastral/src/test/java/com/unipampa/crud/validations/ValidateCpfTest.java +++ b/cadastral/src/test/java/com/unipampa/crud/validations/ValidateCpfTest.java @@ -35,11 +35,11 @@ void setUp() { "Cooper", "Cooper", "123.456.789-00", - "(11) 99999-9999", - "123 Main St, Springfield", "123456", "ADMIN", - UserType.ROLE_ADMINISTRATOR + UserType.ROLE_ADMINISTRATOR, + "(11) 99999-9999", + "123 Main St, Springfield" ); } diff --git a/cadastral/src/test/java/com/unipampa/crud/validations/ValidateEmailTest.java b/cadastral/src/test/java/com/unipampa/crud/validations/ValidateEmailTest.java index 81c1383b..f25ed02f 100644 --- a/cadastral/src/test/java/com/unipampa/crud/validations/ValidateEmailTest.java +++ b/cadastral/src/test/java/com/unipampa/crud/validations/ValidateEmailTest.java @@ -34,11 +34,11 @@ void setUp() { "Cooper", "Cooper", "123.456.789-00", - "(11) 99999-9999", - "123 Main St, Springfield", "123456", "ADMIN", - UserType.ROLE_ADMINISTRATOR + UserType.ROLE_ADMINISTRATOR, + "(11) 99999-9999", + "123 Main St, Springfield" ); } diff --git a/cadastral/src/test/java/com/unipampa/crud/validations/ValidateUserNameTest.java b/cadastral/src/test/java/com/unipampa/crud/validations/ValidateUserNameTest.java index 018065f4..150a1ff8 100644 --- a/cadastral/src/test/java/com/unipampa/crud/validations/ValidateUserNameTest.java +++ b/cadastral/src/test/java/com/unipampa/crud/validations/ValidateUserNameTest.java @@ -34,11 +34,11 @@ void setUp() { "Cooper", "Cooper", "123.456.789-00", - "(11) 99999-9999", - "123 Main St, Springfield", "123456", "ADMIN", - UserType.ROLE_ADMINISTRATOR + UserType.ROLE_ADMINISTRATOR, + "(11) 99999-9999", + "123 Main St, Springfield" ); } From d89e99869e102289c3a2a80e5d79f8b4c501881f Mon Sep 17 00:00:00 2001 From: Samuel Modesto Date: Sat, 27 Dec 2025 17:29:05 -0300 Subject: [PATCH 12/15] trocando autenticacao para usar email --- cadastral/src/main/java/com/unipampa/crud/dto/LoginDTO.java | 6 ++++-- .../main/java/com/unipampa/crud/resources/AuthResource.java | 2 +- .../com/unipampa/crud/validations/ValidateUserNameTest.java | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/cadastral/src/main/java/com/unipampa/crud/dto/LoginDTO.java b/cadastral/src/main/java/com/unipampa/crud/dto/LoginDTO.java index 413497c4..0b775842 100644 --- a/cadastral/src/main/java/com/unipampa/crud/dto/LoginDTO.java +++ b/cadastral/src/main/java/com/unipampa/crud/dto/LoginDTO.java @@ -4,10 +4,12 @@ public record LoginDTO( - @NotBlank String username, @NotBlank - String password + String password, + + @NotBlank + String email ) {} diff --git a/cadastral/src/main/java/com/unipampa/crud/resources/AuthResource.java b/cadastral/src/main/java/com/unipampa/crud/resources/AuthResource.java index 59e472de..fe577635 100644 --- a/cadastral/src/main/java/com/unipampa/crud/resources/AuthResource.java +++ b/cadastral/src/main/java/com/unipampa/crud/resources/AuthResource.java @@ -33,7 +33,7 @@ public class AuthResource { public ResponseEntity authenticateUser(@Valid @RequestBody LoginDTO loginDTO) { try { Authentication authentication = authenticationManager.authenticate( - new UsernamePasswordAuthenticationToken(loginDTO.username(), loginDTO.password())); + new UsernamePasswordAuthenticationToken(loginDTO.email(), loginDTO.password())); SecurityContextHolder.getContext().setAuthentication(authentication); diff --git a/cadastral/src/test/java/com/unipampa/crud/validations/ValidateUserNameTest.java b/cadastral/src/test/java/com/unipampa/crud/validations/ValidateUserNameTest.java index 150a1ff8..0bbbdc6c 100644 --- a/cadastral/src/test/java/com/unipampa/crud/validations/ValidateUserNameTest.java +++ b/cadastral/src/test/java/com/unipampa/crud/validations/ValidateUserNameTest.java @@ -50,7 +50,7 @@ void testValidateUserNameSuccess() { verify(userService).existsByUserName("Cooper"); } - + @Test void testValidateUserNameFailure() { From 18caa8dcf3d7b848a16650b415819b68c7e2f1dd Mon Sep 17 00:00:00 2001 From: Samuel Modesto Date: Sat, 27 Dec 2025 17:47:11 -0300 Subject: [PATCH 13/15] trocando autenticacao para usar email --- .../unipampa/crud/config/security/UserDetailsServiceImpl.java | 3 ++- cadastral/src/main/java/com/unipampa/crud/dto/LoginDTO.java | 4 ++-- .../java/com/unipampa/crud/repository/UserRepository.java | 1 + .../main/java/com/unipampa/crud/resources/AuthResource.java | 4 ++++ 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/cadastral/src/main/java/com/unipampa/crud/config/security/UserDetailsServiceImpl.java b/cadastral/src/main/java/com/unipampa/crud/config/security/UserDetailsServiceImpl.java index f9f5985c..6d3cb4c8 100644 --- a/cadastral/src/main/java/com/unipampa/crud/config/security/UserDetailsServiceImpl.java +++ b/cadastral/src/main/java/com/unipampa/crud/config/security/UserDetailsServiceImpl.java @@ -19,7 +19,8 @@ public class UserDetailsServiceImpl implements UserDetailsService { @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { try { - var user = userRepository.findByUserName(username); + // O parâmetro 'username' agora contém o email + var user = userRepository.findUserByEmail(username); var opt = user.orElseThrow(() -> new UsernameNotFoundException(USER_NOT_FOUND + username)); return UserDatailsImpl.build(opt); } catch (Exception e) { diff --git a/cadastral/src/main/java/com/unipampa/crud/dto/LoginDTO.java b/cadastral/src/main/java/com/unipampa/crud/dto/LoginDTO.java index 0b775842..c044f0a6 100644 --- a/cadastral/src/main/java/com/unipampa/crud/dto/LoginDTO.java +++ b/cadastral/src/main/java/com/unipampa/crud/dto/LoginDTO.java @@ -7,9 +7,9 @@ public record LoginDTO( String username, @NotBlank - String password, + String email, @NotBlank - String email + String password ) {} diff --git a/cadastral/src/main/java/com/unipampa/crud/repository/UserRepository.java b/cadastral/src/main/java/com/unipampa/crud/repository/UserRepository.java index 3afdc61a..722524e1 100644 --- a/cadastral/src/main/java/com/unipampa/crud/repository/UserRepository.java +++ b/cadastral/src/main/java/com/unipampa/crud/repository/UserRepository.java @@ -8,6 +8,7 @@ public interface UserRepository extends MongoRepository { + @EntityGraph(attributePaths = {"roles"}, type = EntityGraph.EntityGraphType.FETCH) Optional findUserByEmail(String email); boolean existsByUserName(String username); diff --git a/cadastral/src/main/java/com/unipampa/crud/resources/AuthResource.java b/cadastral/src/main/java/com/unipampa/crud/resources/AuthResource.java index fe577635..6832c732 100644 --- a/cadastral/src/main/java/com/unipampa/crud/resources/AuthResource.java +++ b/cadastral/src/main/java/com/unipampa/crud/resources/AuthResource.java @@ -8,6 +8,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; @@ -40,6 +41,9 @@ public ResponseEntity authenticateUser(@Valid @RequestBody LoginDTO logi String jwt = jwtProvider.generateJwtToken(authentication); return ResponseEntity.ok(new JwtDTO(jwt)); + } catch (BadCredentialsException e) { + log.error("Credenciais inválidas para: {}", loginDTO.email()); + return ResponseEntity.status(401).body(null); } catch (Exception e) { System.out.println("🚨 Falha na autenticação: " + e.getClass().getSimpleName() + " - " + e.getMessage()); return ResponseEntity.status(401).body(null); From ab75d53f835ebf268a81e7bf510e97a52fd2f6c0 Mon Sep 17 00:00:00 2001 From: Samuel Modesto Date: Sun, 28 Dec 2025 18:23:51 -0300 Subject: [PATCH 14/15] adicionando pesquisa por filtros --- .../crud/dto/AccommodationFilterDTO.java | 38 +++ .../repository/AccommodationRepository.java | 5 +- .../AccommodationRepositoryCustom.java | 21 ++ .../impl/AccommodationRepositoryImpl.java | 83 ++++++ .../crud/resources/AccommodationResource.java | 51 ++++ .../crud/service/AccommodationService.java | 3 + .../impl/AccommodationServiceImpl.java | 7 + .../AccommodationRepositoryFilterTest.java | 252 ++++++++++++++++++ .../impl/AccommodationServiceFilterTest.java | 208 +++++++++++++++ 9 files changed, 667 insertions(+), 1 deletion(-) create mode 100644 cadastral/src/main/java/com/unipampa/crud/dto/AccommodationFilterDTO.java create mode 100644 cadastral/src/main/java/com/unipampa/crud/repository/AccommodationRepositoryCustom.java create mode 100644 cadastral/src/main/java/com/unipampa/crud/repository/impl/AccommodationRepositoryImpl.java create mode 100644 cadastral/src/test/java/com/unipampa/crud/repository/AccommodationRepositoryFilterTest.java create mode 100644 cadastral/src/test/java/com/unipampa/crud/service/impl/AccommodationServiceFilterTest.java diff --git a/cadastral/src/main/java/com/unipampa/crud/dto/AccommodationFilterDTO.java b/cadastral/src/main/java/com/unipampa/crud/dto/AccommodationFilterDTO.java new file mode 100644 index 00000000..9b0668aa --- /dev/null +++ b/cadastral/src/main/java/com/unipampa/crud/dto/AccommodationFilterDTO.java @@ -0,0 +1,38 @@ +package com.unipampa.crud.dto; + +import com.unipampa.crud.enums.AccommodationType; +import io.swagger.v3.oas.annotations.media.Schema; +import java.math.BigDecimal; + +public record AccommodationFilterDTO( + @Schema(example = "Porto Alegre", description = "Cidade da acomodação") + String city, + + @Schema(example = "RS", description = "Estado/UF da acomodação") + String state, + + @Schema(example = "Centro Histórico", description = "Bairro da acomodação") + String neighborhood, + + @Schema(example = "500.00", description = "Preço mínimo da acomodação") + BigDecimal priceMin, + + @Schema(example = "5000.00", description = "Preço máximo da acomodação") + BigDecimal priceMax, + + @Schema(example = "APARTMENT", description = "Tipo de acomodação") + AccommodationType accommodationType, + + @Schema(example = "4", description = "Ocupância máxima mínima") + Integer maxOccupancyMin, + + @Schema(example = "true", description = "Permite animais de estimação") + Boolean allowsPets, + + @Schema(example = "true", description = "Permite crianças") + Boolean allowsChildren, + + @Schema(example = "true", description = "É um alojamento compartilhado") + Boolean isSharedHosting +) {} + diff --git a/cadastral/src/main/java/com/unipampa/crud/repository/AccommodationRepository.java b/cadastral/src/main/java/com/unipampa/crud/repository/AccommodationRepository.java index b8477338..88346198 100644 --- a/cadastral/src/main/java/com/unipampa/crud/repository/AccommodationRepository.java +++ b/cadastral/src/main/java/com/unipampa/crud/repository/AccommodationRepository.java @@ -1,9 +1,12 @@ package com.unipampa.crud.repository; +import com.unipampa.crud.dto.AccommodationFilterDTO; import com.unipampa.crud.entities.Accommodation; import org.springframework.data.mongodb.repository.MongoRepository; -public interface AccommodationRepository extends MongoRepository { +import java.util.List; + +public interface AccommodationRepository extends MongoRepository, AccommodationRepositoryCustom { boolean existsByZipCodeAndStreetNumber(String codeAddress, int streetNumber); diff --git a/cadastral/src/main/java/com/unipampa/crud/repository/AccommodationRepositoryCustom.java b/cadastral/src/main/java/com/unipampa/crud/repository/AccommodationRepositoryCustom.java new file mode 100644 index 00000000..9fd09b0a --- /dev/null +++ b/cadastral/src/main/java/com/unipampa/crud/repository/AccommodationRepositoryCustom.java @@ -0,0 +1,21 @@ +package com.unipampa.crud.repository; + +import com.unipampa.crud.dto.AccommodationFilterDTO; +import com.unipampa.crud.entities.Accommodation; + +import java.util.List; + + +public interface AccommodationRepositoryCustom { + + /** + * Busca acomodações com base em filtros opcionais usando Criteria do MongoDB + * Todos os filtros são opcionais - apenas campos não nulos serão utilizados + * + * @param filters DTO contendo os filtros opcionais + * @return Lista de acomodações que correspondem aos filtros + */ + List findByFilters(AccommodationFilterDTO filters); + +} + diff --git a/cadastral/src/main/java/com/unipampa/crud/repository/impl/AccommodationRepositoryImpl.java b/cadastral/src/main/java/com/unipampa/crud/repository/impl/AccommodationRepositoryImpl.java new file mode 100644 index 00000000..cb778208 --- /dev/null +++ b/cadastral/src/main/java/com/unipampa/crud/repository/impl/AccommodationRepositoryImpl.java @@ -0,0 +1,83 @@ +package com.unipampa.crud.repository.impl; + +import com.unipampa.crud.dto.AccommodationFilterDTO; +import com.unipampa.crud.entities.Accommodation; +import com.unipampa.crud.repository.AccommodationRepositoryCustom; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.stereotype.Repository; + +import java.util.ArrayList; +import java.util.List; + +@Repository +public class AccommodationRepositoryImpl implements AccommodationRepositoryCustom { + + private MongoTemplate mongoTemplate; + + @Autowired + public AccommodationRepositoryImpl(MongoTemplate mongoTemplate) { + this.mongoTemplate = mongoTemplate; + } + + @Override + public List findByFilters(AccommodationFilterDTO filters) { + List criteriaList = new ArrayList<>(); + + if (filters.city() != null && !filters.city().isBlank()) { + criteriaList.add(Criteria.where("city").is(filters.city())); + } + + if (filters.state() != null && !filters.state().isBlank()) { + criteriaList.add(Criteria.where("state").is(filters.state())); + } + + if (filters.neighborhood() != null && !filters.neighborhood().isBlank()) { + criteriaList.add(Criteria.where("neighborhood").is(filters.neighborhood())); + } + + if (filters.accommodationType() != null) { + criteriaList.add(Criteria.where("type").is(filters.accommodationType())); + } + + if (filters.priceMin() != null) { + criteriaList.add(Criteria.where("price").gte(filters.priceMin())); + } + + if (filters.priceMax() != null) { + criteriaList.add(Criteria.where("price").lte(filters.priceMax())); + } + + if (filters.maxOccupancyMin() != null) { + criteriaList.add(Criteria.where("maxOccupancy").gte(filters.maxOccupancyMin())); + } + + if (filters.allowsPets() != null) { + criteriaList.add(Criteria.where("allowsPets").is(filters.allowsPets())); + } + + if (filters.allowsChildren() != null) { + criteriaList.add(Criteria.where("allowsChildren").is(filters.allowsChildren())); + } + + if (filters.isSharedHosting() != null) { + criteriaList.add(Criteria.where("isSharedHosting").is(filters.isSharedHosting())); + } + + Query query; + if (criteriaList.isEmpty()) { + query = new Query(); + } else { + Criteria combinedCriteria = new Criteria().andOperator( + criteriaList.toArray(new Criteria[0]) + ); + query = new Query(combinedCriteria); + } + + return mongoTemplate.find(query, Accommodation.class); + } + +} + diff --git a/cadastral/src/main/java/com/unipampa/crud/resources/AccommodationResource.java b/cadastral/src/main/java/com/unipampa/crud/resources/AccommodationResource.java index eb9b3767..27cb5c00 100644 --- a/cadastral/src/main/java/com/unipampa/crud/resources/AccommodationResource.java +++ b/cadastral/src/main/java/com/unipampa/crud/resources/AccommodationResource.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.unipampa.crud.config.security.SecurityUtil; import com.unipampa.crud.dto.AccommodationDTO; +import com.unipampa.crud.dto.AccommodationFilterDTO; import com.unipampa.crud.dto.AccommodationRequestDTO; import com.unipampa.crud.dto.ErrorResponse; import com.unipampa.crud.entities.Accommodation; @@ -36,6 +37,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.time.LocalDateTime; +import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; @@ -189,6 +191,55 @@ public ResponseEntity> findAll() { return ResponseEntity.ok(accommodationDtos); } + @GetMapping("/search") + @Operation(summary = "Buscar acomodações com filtros opcionais", + description = "Retorna uma lista de acomodações baseada em filtros opcionais. Todos os parâmetros são opcionais - apenas os filtros fornecidos serão aplicados.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Lista filtrada retornada com sucesso", + content = @Content(schema = @Schema(implementation = AccommodationDTO.class))) + }) + public ResponseEntity> searchWithFilters( + @RequestParam(required = false) String city, + @RequestParam(required = false) String state, + @RequestParam(required = false) String neighborhood, + @RequestParam(required = false) java.math.BigDecimal priceMin, + @RequestParam(required = false) java.math.BigDecimal priceMax, + @RequestParam(required = false) String accommodationType, + @RequestParam(required = false) Integer maxOccupancyMin, + @RequestParam(required = false) Boolean allowsPets, + @RequestParam(required = false) Boolean allowsChildren, + @RequestParam(required = false) Boolean isSharedHosting) { + + com.unipampa.crud.enums.AccommodationType type = null; + if (accommodationType != null && !accommodationType.isBlank()) { + try { + type = com.unipampa.crud.enums.AccommodationType.valueOf(accommodationType.toUpperCase()); + } catch (IllegalArgumentException e) { + return ResponseEntity.ok(new ArrayList<>()); + } + } + + AccommodationFilterDTO filterDTO = new AccommodationFilterDTO( + city, + state, + neighborhood, + priceMin, + priceMax, + type, + maxOccupancyMin, + allowsPets, + allowsChildren, + isSharedHosting + ); + + List accommodationDtos = accommodationService.findByFilters(filterDTO) + .stream() + .map(accommodation -> accommodationMapper.toDTO(accommodation)) + .collect(Collectors.toList()); + + return ResponseEntity.ok(accommodationDtos); + } + @GetMapping("{id}") @Operation(summary = "Buscar acomodação por ID", description = "Retorna os dados de uma acomodação específica a partir do seu ID.") diff --git a/cadastral/src/main/java/com/unipampa/crud/service/AccommodationService.java b/cadastral/src/main/java/com/unipampa/crud/service/AccommodationService.java index 715283a0..31866f80 100644 --- a/cadastral/src/main/java/com/unipampa/crud/service/AccommodationService.java +++ b/cadastral/src/main/java/com/unipampa/crud/service/AccommodationService.java @@ -1,5 +1,6 @@ package com.unipampa.crud.service; +import com.unipampa.crud.dto.AccommodationFilterDTO; import com.unipampa.crud.entities.Accommodation; import org.springframework.web.multipart.MultipartFile; @@ -15,6 +16,8 @@ public interface AccommodationService { List findAll(); + List findByFilters(AccommodationFilterDTO filters); + void delete(String id); boolean existsByCodAddressAndNumber(String codeAddress, int number); diff --git a/cadastral/src/main/java/com/unipampa/crud/service/impl/AccommodationServiceImpl.java b/cadastral/src/main/java/com/unipampa/crud/service/impl/AccommodationServiceImpl.java index 3b97814e..9ac88c57 100644 --- a/cadastral/src/main/java/com/unipampa/crud/service/impl/AccommodationServiceImpl.java +++ b/cadastral/src/main/java/com/unipampa/crud/service/impl/AccommodationServiceImpl.java @@ -1,6 +1,7 @@ package com.unipampa.crud.service.impl; import com.unipampa.crud.config.security.SecurityUtil; +import com.unipampa.crud.dto.AccommodationFilterDTO; import com.unipampa.crud.entities.Accommodation; import com.unipampa.crud.enums.AccommodationStats; import com.unipampa.crud.repository.AccommodationRepository; @@ -69,6 +70,12 @@ public List findAll() { return propertyRepository.findAll(); } + + @Override + public List findByFilters(AccommodationFilterDTO filters) { + return propertyRepository.findByFilters(filters); + } + @Override public void delete(String id) { Accommodation property = propertyRepository.findById(id) diff --git a/cadastral/src/test/java/com/unipampa/crud/repository/AccommodationRepositoryFilterTest.java b/cadastral/src/test/java/com/unipampa/crud/repository/AccommodationRepositoryFilterTest.java new file mode 100644 index 00000000..0f0844a2 --- /dev/null +++ b/cadastral/src/test/java/com/unipampa/crud/repository/AccommodationRepositoryFilterTest.java @@ -0,0 +1,252 @@ +package com.unipampa.crud.repository; + +import com.unipampa.crud.dto.AccommodationFilterDTO; +import com.unipampa.crud.entities.Accommodation; +import com.unipampa.crud.enums.AccommodationType; +import com.unipampa.crud.enums.AccommodationStats; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest; +import org.springframework.test.context.ActiveProfiles; + +import java.math.BigDecimal; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +@DataMongoTest +@ActiveProfiles("test") +@DisplayName("Testes do AccommodationRepository com Filtros") +class AccommodationRepositoryFilterTest { + + @Autowired + private AccommodationRepository repository; + + private Accommodation accommodation1; + private Accommodation accommodation2; + private Accommodation accommodation3; + + @BeforeEach + void setUp() { + repository.deleteAll(); + + // Acomodação 1: Apartamento em Porto Alegre + accommodation1 = Accommodation.builder() + .title("Apartamento Moderno") + .description("Apartamento bem iluminado") + .city("Porto Alegre") + .state("RS") + .neighborhood("Centro") + .price(new BigDecimal("2500.00")) + .type(AccommodationType.APARTMENT) + .maxOccupancy(4) + .roomCount(3) + .bathroomCount(1) + .allowsPets(true) + .allowsChildren(true) + .isSharedHosting(false) + .stats(AccommodationStats.AVAILABLE) + .hostId("host1") + .build(); + + // Acomodação 2: Casa em Viamão + accommodation2 = Accommodation.builder() + .title("Casa Confortável") + .description("Casa com jardim") + .city("Viamão") + .state("RS") + .neighborhood("Bonsucesso") + .price(new BigDecimal("1500.00")) + .type(AccommodationType.HOUSE) + .maxOccupancy(6) + .roomCount(4) + .bathroomCount(2) + .allowsPets(false) + .allowsChildren(true) + .isSharedHosting(false) + .stats(AccommodationStats.AVAILABLE) + .hostId("host2") + .build(); + + // Acomodação 3: Studio em Porto Alegre + accommodation3 = Accommodation.builder() + .title("Studio Aconchegante") + .description("Studio com vista para o parque") + .city("Porto Alegre") + .state("RS") + .neighborhood("Moinhos") + .price(new BigDecimal("800.00")) + .type(AccommodationType.APARTMENT) + .maxOccupancy(2) + .roomCount(1) + .bathroomCount(1) + .allowsPets(true) + .allowsChildren(false) + .isSharedHosting(true) + .stats(AccommodationStats.AVAILABLE) + .hostId("host3") + .build(); + + repository.save(accommodation1); + repository.save(accommodation2); + repository.save(accommodation3); + } + + @Test + @DisplayName("Deve retornar todas as acomodações quando nenhum filtro é fornecido") + void testFindByFiltersNoFilters() { + AccommodationFilterDTO filters = new AccommodationFilterDTO(null, null, null, null, null, null, null, null, null, null); + List result = repository.findByFilters(filters); + + assertEquals(3, result.size()); + } + + @Test + @DisplayName("Deve filtrar por cidade") + void testFindByFiltersCity() { + AccommodationFilterDTO filters = new AccommodationFilterDTO("Porto Alegre", null, null, null, null, null, null, null, null, null); + List result = repository.findByFilters(filters); + + assertEquals(2, result.size()); + assertTrue(result.stream().allMatch(a -> a.getCity().equals("Porto Alegre"))); + } + + @Test + @DisplayName("Deve filtrar por preço mínimo") + void testFindByFiltersPriceMin() { + AccommodationFilterDTO filters = new AccommodationFilterDTO(null, null, null, new BigDecimal("1500.00"), null, null, null, null, null, null); + List result = repository.findByFilters(filters); + + assertEquals(2, result.size()); + assertTrue(result.stream().allMatch(a -> a.getPrice().compareTo(new BigDecimal("1500.00")) >= 0)); + } + + @Test + @DisplayName("Deve filtrar por preço máximo") + void testFindByFiltersPriceMax() { + AccommodationFilterDTO filters = new AccommodationFilterDTO(null, null, null, null, new BigDecimal("1500.00"), null, null, null, null, null); + List result = repository.findByFilters(filters); + + assertEquals(2, result.size()); + assertTrue(result.stream().allMatch(a -> a.getPrice().compareTo(new BigDecimal("1500.00")) <= 0)); + } + + @Test + @DisplayName("Deve filtrar por tipo de acomodação") + void testFindByFiltersType() { + AccommodationFilterDTO filters = new AccommodationFilterDTO(null, null, null, null, null, AccommodationType.APARTMENT, null, null, null, null); + List result = repository.findByFilters(filters); + + assertEquals(1, result.size()); + assertEquals(AccommodationType.APARTMENT, result.get(0).getType()); + } + + @Test + @DisplayName("Deve filtrar por permite pets") + void testFindByFiltersAllowsPets() { + AccommodationFilterDTO filters = new AccommodationFilterDTO(null, null, null, null, null, null, null, true, null, null); + List result = repository.findByFilters(filters); + + assertEquals(2, result.size()); + assertTrue(result.stream().allMatch(Accommodation::isAllowsPets)); + } + + @Test + @DisplayName("Deve filtrar por permite crianças") + void testFindByFiltersAllowsChildren() { + AccommodationFilterDTO filters = new AccommodationFilterDTO(null, null, null, null, null, null, null, null, true, null); + List result = repository.findByFilters(filters); + + assertEquals(2, result.size()); + assertTrue(result.stream().allMatch(Accommodation::isAllowsChildren)); + } + + @Test + @DisplayName("Deve filtrar por ocupância máxima mínima") + void testFindByFiltersMaxOccupancy() { + AccommodationFilterDTO filters = new AccommodationFilterDTO(null, null, null, null, null, null, 4, null, null, null); + List result = repository.findByFilters(filters); + + assertEquals(2, result.size()); + assertTrue(result.stream().allMatch(a -> a.getMaxOccupancy() >= 4)); + } + + @Test + @DisplayName("Deve filtrar por alojamento compartilhado") + void testFindByFiltersSharedHosting() { + AccommodationFilterDTO filters = new AccommodationFilterDTO(null, null, null, null, null, null, null, null, null, true); + List result = repository.findByFilters(filters); + + assertEquals(1, result.size()); + assertTrue(result.get(0).isSharedHosting()); + } + + @Test + @DisplayName("Deve aplicar múltiplos filtros simultaneamente (AND lógico)") + void testFindByFiltersMultipleFilters() { + AccommodationFilterDTO filters = new AccommodationFilterDTO( + "Porto Alegre", // city + null, // state + null, // neighborhood + null, // priceMin + new BigDecimal("2000.00"), // priceMax + null, // accommodationType + null, // maxOccupancyMin + true, // allowsPets + null, // allowsChildren + null // isSharedHosting + ); + List result = repository.findByFilters(filters); + + assertEquals(1, result.size()); + assertEquals(accommodation3, result.get(0)); + } + + @Test + @DisplayName("Deve retornar lista vazia quando nenhuma acomodação corresponde aos filtros") + void testFindByFiltersNoMatches() { + AccommodationFilterDTO filters = new AccommodationFilterDTO( + "São Paulo", // city inexistente + null, + null, + null, + null, + null, + null, + null, + null, + null + ); + List result = repository.findByFilters(filters); + + assertTrue(result.isEmpty()); + } + + @Test + @DisplayName("Deve filtrar por faixa de preço (min e max)") + void testFindByFiltersPriceRange() { + AccommodationFilterDTO filters = new AccommodationFilterDTO( + null, + null, + null, + new BigDecimal("1000.00"), // priceMin + new BigDecimal("2600.00"), // priceMax + null, + null, + null, + null, + null + ); + List result = repository.findByFilters(filters); + + assertEquals(2, result.size()); + assertTrue(result.stream().allMatch(a -> + a.getPrice().compareTo(new BigDecimal("1000.00")) >= 0 && + a.getPrice().compareTo(new BigDecimal("2600.00")) <= 0 + )); + } + +} + diff --git a/cadastral/src/test/java/com/unipampa/crud/service/impl/AccommodationServiceFilterTest.java b/cadastral/src/test/java/com/unipampa/crud/service/impl/AccommodationServiceFilterTest.java new file mode 100644 index 00000000..ab728f3e --- /dev/null +++ b/cadastral/src/test/java/com/unipampa/crud/service/impl/AccommodationServiceFilterTest.java @@ -0,0 +1,208 @@ +package com.unipampa.crud.service.impl; + +import com.unipampa.crud.dto.AccommodationFilterDTO; +import com.unipampa.crud.entities.Accommodation; +import com.unipampa.crud.enums.AccommodationType; +import com.unipampa.crud.enums.AccommodationStats; +import com.unipampa.crud.repository.AccommodationRepository; +import com.unipampa.crud.sender.AccommodationSender; +import com.unipampa.crud.service.ImageService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.math.BigDecimal; +import java.util.Arrays; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +@DisplayName("Testes do AccommodationService com Filtros") +class AccommodationServiceFilterTest { + + @Mock + private AccommodationRepository accommodationRepository; + + @Mock + private AccommodationSender accommodationSender; + + @Mock + private ImageService imageService; + + @InjectMocks + private AccommodationServiceImpl accommodationService; + + private Accommodation accommodation1; + private Accommodation accommodation2; + private Accommodation accommodation3; + + @BeforeEach + void setUp() { + // Acomodação 1 + accommodation1 = Accommodation.builder() + .id("1") + .title("Apartamento Moderno") + .city("Porto Alegre") + .state("RS") + .neighborhood("Centro") + .price(new BigDecimal("2500.00")) + .accommodationType(AccommodationType.APARTMENT) + .maxOccupancy(4) + .allowsPets(true) + .allowsChildren(true) + .isSharedHosting(false) + .stats(AccommodationStats.AVAILABLE) + .hostId("host1") + .build(); + + // Acomodação 2 + accommodation2 = Accommodation.builder() + .id("2") + .title("Casa Confortável") + .city("Viamão") + .state("RS") + .neighborhood("Bonsucesso") + .price(new BigDecimal("1500.00")) + .accommodationType(AccommodationType.HOUSE) + .maxOccupancy(6) + .allowsPets(false) + .allowsChildren(true) + .isSharedHosting(false) + .stats(AccommodationStats.AVAILABLE) + .hostId("host2") + .build(); + + // Acomodação 3 + accommodation3 = Accommodation.builder() + .id("3") + .title("Studio Aconchegante") + .city("Porto Alegre") + .state("RS") + .neighborhood("Moinhos") + .price(new BigDecimal("800.00")) + .type(AccommodationType.APARTMENT) + .maxOccupancy(2) + .allowsPets(true) + .allowsChildren(false) + .isSharedHosting(true) + .stats(AccommodationStats.AVAILABLE) + .hostId("host3") + .build(); + } + + @Test + @DisplayName("Deve retornar acomodações filtradas por cidade") + void testFindByFiltersCityFilter() { + AccommodationFilterDTO filters = new AccommodationFilterDTO( + "Porto Alegre", null, null, null, null, null, null, null, null, null + ); + + when(accommodationRepository.findByFilters(filters)) + .thenReturn(Arrays.asList(accommodation1, accommodation3)); + + List result = accommodationService.findByFilters(filters); + + assertEquals(2, result.size()); + assertTrue(result.stream().allMatch(a -> a.getCity().equals("Porto Alegre"))); + } + + @Test + @DisplayName("Deve retornar acomodações filtradas por preço") + void testFindByFiltersPriceFilter() { + AccommodationFilterDTO filters = new AccommodationFilterDTO( + null, null, null, new BigDecimal("1000.00"), new BigDecimal("2600.00"), null, null, null, null, null + ); + + when(accommodationRepository.findByFilters(filters)) + .thenReturn(Arrays.asList(accommodation2, accommodation1)); + + List result = accommodationService.findByFilters(filters); + + assertEquals(2, result.size()); + assertTrue(result.stream().allMatch(a -> + a.getPrice().compareTo(new BigDecimal("1000.00")) >= 0 && + a.getPrice().compareTo(new BigDecimal("2600.00")) <= 0 + )); + } + + @Test + @DisplayName("Deve retornar acomodações que permitem pets") + void testFindByFiltersAllowsPetsFilter() { + AccommodationFilterDTO filters = new AccommodationFilterDTO( + null, null, null, null, null, null, null, true, null, null + ); + + when(accommodationRepository.findByFilters(filters)) + .thenReturn(Arrays.asList(accommodation1, accommodation3)); + + List result = accommodationService.findByFilters(filters); + + assertEquals(2, result.size()); + assertTrue(result.stream().allMatch(Accommodation::isAllowsPets)); + } + + @Test + @DisplayName("Deve retornar acomodações por tipo") + void testFindByFiltersTypeFilter() { + AccommodationFilterDTO filters = new AccommodationFilterDTO( + null, null, null, null, null, AccommodationType.HOUSE, null, null, null, null + ); + + when(accommodationRepository.findByFilters(filters)) + .thenReturn(Arrays.asList(accommodation2)); + + List result = accommodationService.findByFilters(filters); + + assertEquals(1, result.size()); + assertEquals(AccommodationType.HOUSE, result.get(0).getType()); + } + + @Test + @DisplayName("Deve retornar lista vazia quando nenhuma acomodação corresponde aos filtros") + void testFindByFiltersNoMatches() { + AccommodationFilterDTO filters = new AccommodationFilterDTO( + "São Paulo", null, null, null, null, null, null, null, null, null + ); + + when(accommodationRepository.findByFilters(filters)) + .thenReturn(Arrays.asList()); + + List result = accommodationService.findByFilters(filters); + + assertTrue(result.isEmpty()); + } + + @Test + @DisplayName("Deve retornar todas as acomodações com múltiplos filtros") + void testFindByFiltersMultipleFilters() { + AccommodationFilterDTO filters = new AccommodationFilterDTO( + "Porto Alegre", // city + null, // state + null, // neighborhood + null, // priceMin + new BigDecimal("2000.00"), // priceMax + null, // accommodationType + null, // maxOccupancyMin + true, // allowsPets + null, // allowsChildren + null // isSharedHosting + ); + + when(accommodationRepository.findByFilters(filters)) + .thenReturn(Arrays.asList(accommodation3)); + + List result = accommodationService.findByFilters(filters); + + assertEquals(1, result.size()); + assertEquals(accommodation3, result.get(0)); + } + +} + From 53c330e55aa52f2f8a9a98b9874e26540cd7adb5 Mon Sep 17 00:00:00 2001 From: Samuel Modesto Date: Sun, 28 Dec 2025 20:14:22 -0300 Subject: [PATCH 15/15] corrigindo o tipo do imovel que nao estava desserializando --- .../crud/dto/AccommodationRequestDTO.java | 6 +-- .../crud/enums/AccommodationType.java | 9 ++++ .../crud/mappers/AccommodationMapper.java | 19 +++++++- .../crud/resources/AccommodationResource.java | 45 +++++++++++++++---- .../resources/AccommodationResourceTest.java | 3 +- .../impl/AccommodationServiceFilterTest.java | 4 +- .../ValidateAccommodationRegisteredTest.java | 3 +- 7 files changed, 71 insertions(+), 18 deletions(-) diff --git a/cadastral/src/main/java/com/unipampa/crud/dto/AccommodationRequestDTO.java b/cadastral/src/main/java/com/unipampa/crud/dto/AccommodationRequestDTO.java index 26f412f1..5adaef99 100644 --- a/cadastral/src/main/java/com/unipampa/crud/dto/AccommodationRequestDTO.java +++ b/cadastral/src/main/java/com/unipampa/crud/dto/AccommodationRequestDTO.java @@ -1,5 +1,6 @@ package com.unipampa.crud.dto; +import com.fasterxml.jackson.annotation.JsonProperty; import com.unipampa.crud.enums.AccommodationType; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; @@ -46,6 +47,7 @@ public record AccommodationRequestDTO( Integer imageQuantity, @NotNull + @JsonProperty("accommodationType") @Schema(example = "APARTMENT") AccommodationType accommodationType, @@ -70,8 +72,6 @@ public record AccommodationRequestDTO( Boolean isSharedHosting, @Schema(example = "[]") - List imagesUrls, + List imagesUrls - @NotBlank - String hostId ) {} diff --git a/cadastral/src/main/java/com/unipampa/crud/enums/AccommodationType.java b/cadastral/src/main/java/com/unipampa/crud/enums/AccommodationType.java index 838a0915..8f574e6f 100644 --- a/cadastral/src/main/java/com/unipampa/crud/enums/AccommodationType.java +++ b/cadastral/src/main/java/com/unipampa/crud/enums/AccommodationType.java @@ -1,5 +1,6 @@ package com.unipampa.crud.enums; +import com.fasterxml.jackson.annotation.JsonCreator; import io.swagger.v3.oas.annotations.media.Schema; public enum AccommodationType { @@ -9,4 +10,12 @@ public enum AccommodationType { @Schema(description = "Casa") HOUSE; + + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static AccommodationType forValue(String value) { + if (value == null || value.trim().isEmpty()) { + return null; + } + return AccommodationType.valueOf(value.toUpperCase().trim()); + } } diff --git a/cadastral/src/main/java/com/unipampa/crud/mappers/AccommodationMapper.java b/cadastral/src/main/java/com/unipampa/crud/mappers/AccommodationMapper.java index c571ef98..aa870833 100644 --- a/cadastral/src/main/java/com/unipampa/crud/mappers/AccommodationMapper.java +++ b/cadastral/src/main/java/com/unipampa/crud/mappers/AccommodationMapper.java @@ -32,7 +32,24 @@ public Accommodation toEntity(AccommodationDTO dto) { } public Accommodation toEntity(AccommodationRequestDTO requestDTO) { - return objectMapper.convertValue(requestDTO, Accommodation.class); + return Accommodation.builder() + .title(requestDTO.title()) + .neighborhood(requestDTO.neighborhood()) + .zipCode(requestDTO.codAddress()) + .city(requestDTO.city()) + .description(requestDTO.description()) + .address(requestDTO.address()) + .state(requestDTO.state()) + .price(requestDTO.price()) + .streetNumber(requestDTO.streetNumber()) + .type(requestDTO.accommodationType()) // Mapeia accommodationType -> type + .maxOccupancy(requestDTO.maxOccupancy()) + .roomCount(requestDTO.roomCount()) + .bathroomCount(requestDTO.bathroomCount()) + .allowsPets(requestDTO.allowsPets()) + .isSharedHosting(requestDTO.isSharedHosting()) + .imagesUrls(requestDTO.imagesUrls()) + .build(); } public AccommodationDTO toDTO(Accommodation entity) { diff --git a/cadastral/src/main/java/com/unipampa/crud/resources/AccommodationResource.java b/cadastral/src/main/java/com/unipampa/crud/resources/AccommodationResource.java index 27cb5c00..c56d4066 100644 --- a/cadastral/src/main/java/com/unipampa/crud/resources/AccommodationResource.java +++ b/cadastral/src/main/java/com/unipampa/crud/resources/AccommodationResource.java @@ -79,16 +79,31 @@ public ResponseEntity save( ) throws IOException { ObjectMapper mapper = new ObjectMapper(); - AccommodationRequestDTO accommodationDTO = mapper.readValue(dadosJson, AccommodationRequestDTO.class); + mapper.enable(com.fasterxml.jackson.databind.DeserializationFeature.READ_ENUMS_USING_TO_STRING); + // Limpar e unescape o JSON recebido como string de formulário + String jsonString = dadosJson.trim(); + if (jsonString.startsWith("\"") && jsonString.endsWith("\"")) { + jsonString = jsonString.substring(1, jsonString.length() - 1); + } + jsonString = jsonString.replace("\\\"", "\"") + .replace("\\n", "\n") + .replace("\\t", "\t") + .replace("\\\\", "\\"); + + // Desserializar como JsonNode para garantir conversão correta do enum + com.fasterxml.jackson.databind.JsonNode node = mapper.readTree(jsonString); + if (node.get("accommodationType") != null && !node.get("accommodationType").isNull()) { + String accommodationTypeStr = node.get("accommodationType").asText().toUpperCase(); + ((com.fasterxml.jackson.databind.node.ObjectNode) node).put("accommodationType", accommodationTypeStr); + } + + final AccommodationRequestDTO accommodationDTO = mapper.treeToValue(node, AccommodationRequestDTO.class); validations.forEach(e -> e.validate(accommodationDTO)); var accommodation = accommodationMapper.toEntity(accommodationDTO); - String novoId = new ObjectId().toString(); - accommodation.setId(novoId); - - String authenticatedUserId = SecurityUtil.getAuthenticatedUserId(); - accommodation.setHostId(authenticatedUserId); + accommodation.setId(new ObjectId().toString()); + accommodation.setHostId(SecurityUtil.getAuthenticatedUserId()); accommodation.setStats(AccommodationStats.AVAILABLE); accommodationService.save(accommodation, images); @@ -141,13 +156,27 @@ public ResponseEntity updateAccommodation( accommodationService.validateAuthorizationUser(existingAccommodation); ObjectMapper mapper = new ObjectMapper(); - AccommodationRequestDTO accommodationDTO = mapper.readValue(dadosJson, AccommodationRequestDTO.class); + mapper.enable(com.fasterxml.jackson.databind.DeserializationFeature.READ_ENUMS_USING_TO_STRING); + String jsonString = dadosJson.trim(); + if (jsonString.startsWith("\"") && jsonString.endsWith("\"")) { + jsonString = jsonString.substring(1, jsonString.length() - 1); + } + jsonString = jsonString.replace("\\\"", "\"") + .replace("\\n", "\n") + .replace("\\t", "\t") + .replace("\\\\", "\\"); + + com.fasterxml.jackson.databind.JsonNode node = mapper.readTree(jsonString); + if (node.get("accommodationType") != null && !node.get("accommodationType").isNull()) { + String accommodationTypeStr = node.get("accommodationType").asText().toUpperCase(); + ((com.fasterxml.jackson.databind.node.ObjectNode) node).put("accommodationType", accommodationTypeStr); + } + final AccommodationRequestDTO accommodationDTO = mapper.treeToValue(node, AccommodationRequestDTO.class); validations.forEach(e -> e.validate(accommodationDTO)); Accommodation accommodation = existingAccommodation.get(); - accommodation.setTitle(accommodationDTO.title()); accommodation.setAddress(accommodationDTO.address()); accommodation.setPrice(accommodationDTO.price()); diff --git a/cadastral/src/test/java/com/unipampa/crud/resources/AccommodationResourceTest.java b/cadastral/src/test/java/com/unipampa/crud/resources/AccommodationResourceTest.java index a33ed0cf..b1836d90 100644 --- a/cadastral/src/test/java/com/unipampa/crud/resources/AccommodationResourceTest.java +++ b/cadastral/src/test/java/com/unipampa/crud/resources/AccommodationResourceTest.java @@ -66,8 +66,7 @@ void setUp() { 1, true, false, - List.of("https://img.com/1.jpg", "https://img.com/2.jpg"), - "123345" + List.of("https://img.com/1.jpg", "https://img.com/2.jpg") ); accommodation = Accommodation.builder().build(); diff --git a/cadastral/src/test/java/com/unipampa/crud/service/impl/AccommodationServiceFilterTest.java b/cadastral/src/test/java/com/unipampa/crud/service/impl/AccommodationServiceFilterTest.java index ab728f3e..dec4399d 100644 --- a/cadastral/src/test/java/com/unipampa/crud/service/impl/AccommodationServiceFilterTest.java +++ b/cadastral/src/test/java/com/unipampa/crud/service/impl/AccommodationServiceFilterTest.java @@ -53,7 +53,7 @@ void setUp() { .state("RS") .neighborhood("Centro") .price(new BigDecimal("2500.00")) - .accommodationType(AccommodationType.APARTMENT) + .type(AccommodationType.APARTMENT) .maxOccupancy(4) .allowsPets(true) .allowsChildren(true) @@ -70,7 +70,7 @@ void setUp() { .state("RS") .neighborhood("Bonsucesso") .price(new BigDecimal("1500.00")) - .accommodationType(AccommodationType.HOUSE) + .type(AccommodationType.HOUSE) .maxOccupancy(6) .allowsPets(false) .allowsChildren(true) diff --git a/cadastral/src/test/java/com/unipampa/crud/validations/impl/ValidateAccommodationRegisteredTest.java b/cadastral/src/test/java/com/unipampa/crud/validations/impl/ValidateAccommodationRegisteredTest.java index 1542ccb2..253672ae 100644 --- a/cadastral/src/test/java/com/unipampa/crud/validations/impl/ValidateAccommodationRegisteredTest.java +++ b/cadastral/src/test/java/com/unipampa/crud/validations/impl/ValidateAccommodationRegisteredTest.java @@ -48,8 +48,7 @@ void setUp() { 2, true, false, - List.of("https://img.com/1.jpg", "https://img.com/2.jpg"), - "12345" + List.of("https://img.com/1.jpg", "https://img.com/2.jpg") ); }