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/pom.xml b/cadastral/pom.xml
index b31f3daf..bf30e24c 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
-
+
+
+
+
@@ -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/config/MongoScriptInitializer.java b/cadastral/src/main/java/com/unipampa/crud/config/MongoScriptInitializer.java
index 1523c904..192786eb 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,31 @@ 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("email", System.getenv("ADMIN1_EMAIL"))
.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("email", System.getenv("ADMIN2_EMAIL"))
.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("email", System.getenv("ADMIN3_EMAIL"))
.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("email", System.getenv("ADMIN4_EMAIL"))
.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/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/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/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/dto/AccommodationRequestDTO.java b/cadastral/src/main/java/com/unipampa/crud/dto/AccommodationRequestDTO.java
index 281ec649..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;
@@ -10,7 +11,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 +25,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")
@@ -46,6 +47,7 @@ public record AccommodationRequestDTO(
Integer imageQuantity,
@NotNull
+ @JsonProperty("accommodationType")
@Schema(example = "APARTMENT")
AccommodationType accommodationType,
@@ -53,9 +55,23 @@ public record AccommodationRequestDTO(
@Schema(example = "4")
Integer maxOccupancy,
- @Schema(example = "[\"https://img.com/1.jpg\", \"https://img.com/2.jpg\"]")
- List imagesUrls,
+ @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
- String hostId
) {}
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..c044f0a6 100644
--- a/cadastral/src/main/java/com/unipampa/crud/dto/LoginDTO.java
+++ b/cadastral/src/main/java/com/unipampa/crud/dto/LoginDTO.java
@@ -4,9 +4,11 @@
public record LoginDTO(
- @NotBlank
String username,
+ @NotBlank
+ String email,
+
@NotBlank
String password
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
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 df904d48..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,22 +32,31 @@ 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) {
- 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(),
entity.getTitle(),
entity.getNeighborhood(),
entity.getZipCode(),
@@ -57,12 +66,15 @@ 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(),
+ entity.getRoomCount(),
+ entity.getBathroomCount(),
+ entity.isAllowsPets(),
+ entity.isSharedHosting(),
imageUrls
);
-
-
}
+
}
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/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/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 e542830f..c56d4066 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;
@@ -77,15 +79,33 @@ 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);
URI location = URI.create("/accommodations/" + accommodation.getId());
@@ -136,16 +156,42 @@ public ResponseEntity
-
-
-
-
- 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
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 {