From e355d41ec7359c37245acd9bf43ba8935f45c3fd Mon Sep 17 00:00:00 2001 From: "warley.rocha" Date: Mon, 1 Jul 2019 15:22:56 +0100 Subject: [PATCH 1/9] =?UTF-8?q?Configura=C3=A7=C3=A3o=20do=20Sistema?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 226 ++++++++++++++++++ .../java/br/com/zup/way/WayApplication.java | 13 + src/main/resources/application.properties | 24 ++ .../br/com/zup/way/WayApplicationTests.java | 17 ++ 4 files changed, 280 insertions(+) create mode 100644 pom.xml create mode 100644 src/main/java/br/com/zup/way/WayApplication.java create mode 100644 src/main/resources/application.properties create mode 100644 src/test/java/br/com/zup/way/WayApplicationTests.java diff --git a/pom.xml b/pom.xml new file mode 100644 index 00000000..7c7768f6 --- /dev/null +++ b/pom.xml @@ -0,0 +1,226 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.1.6.RELEASE + + + br.com.zup + way + 0.0.1-SNAPSHOT + way + Teste Java BackEnd + + + 1.8 + 1.3.0.Final + 1.18.8 + 2.3.5.RELEASE + 1.0.10.RELEASE + + + + + dev + + true + + + dev + + + + test + + test + + + + + + + org.springframework.boot + spring-boot-starter-data-rest + + + + org.springframework.boot + spring-boot-starter-security + + + + io.dropwizard.metrics + metrics-core + 3.2.6 + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-devtools + runtime + true + + + + org.projectlombok + lombok + true + + + + org.mapstruct + mapstruct + ${org.mapstruct.version} + + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.springframework.security + spring-security-test + test + + + + io.springfox + springfox-swagger2 + 2.9.2 + + + + org.springframework.boot + spring-boot-starter-data-solr + + + + org.apache.solr + solr-solrj + + + + org.apache.solr + solr-core + + + + org.springframework.data + spring-data-solr + + + + + org.springframework.security.oauth + spring-security-oauth2 + ${oauth.version} + + + + org.springframework.security + spring-security-jwt + ${jwt.version} + + + + io.springfox + springfox-swagger-ui + 2.9.2 + + + + org.mockito + mockito-core + 2.11.0 + compile + + + + org.springframework.data + spring-data-jpa + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + org.postgresql + postgresql + runtime + + + + org.apache.commons + commons-lang3 + + + + + + org.flywaydb + flyway-core + 5.2.4 + + + + com.h2database + h2 + runtime + + + + io.jsonwebtoken + jjwt + 0.9.1 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + true + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + + ${java.version} + ${java.version} + + + org.mapstruct + mapstruct-processor + ${org.mapstruct.version} + + + org.projectlombok + lombok + ${org.projectlombok.version} + + + + + + + + + diff --git a/src/main/java/br/com/zup/way/WayApplication.java b/src/main/java/br/com/zup/way/WayApplication.java new file mode 100644 index 00000000..4c85ac2b --- /dev/null +++ b/src/main/java/br/com/zup/way/WayApplication.java @@ -0,0 +1,13 @@ +package br.com.zup.way; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class WayApplication { + + public static void main(String[] args) { + SpringApplication.run(WayApplication.class, args); + } + +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties new file mode 100644 index 00000000..f30c8236 --- /dev/null +++ b/src/main/resources/application.properties @@ -0,0 +1,24 @@ +way.jwt.expiration=86400000 +way.jwt.secret=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxkZXIiLCJpYXQiOjE1NjE0NzExMDksImV4cCI6MTU2MTQ3MTEwNywiYXVkIjoid3d3LmV4YW1wbGUuY29tIiwic3ViIjoianJvY2tldEBleGFtcGxlLmNvbSIsIkdpdmVuTmFtZSI6IkpvaG5ueSIsIlN1cm5hbWUiOiJSb2NrZXQiLCJFbWFpbCI6Impyb2NrZXRAZXhhbXBsZS5jb20iLCJSb2xlIjpbIk1hbmFnZXIiLCJQcm9qZWN0IEFkbWluaXN0cmF0b3IiXX0.9ZnHxfOJs9ikez4ms8ZVNQHkaieQ-BON40mrLEKQGwU + +spring.main.allow-bean-definition-overriding=true + +# DATASOURCE + +spring.profiles.active=@spring.profiles.active@ +spring.jpa.generate-ddl=false +spring.jpa.hibernate.ddl-auto=none +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect +spring.jpa.properties.hibernate.default_schema=PUBLIC +spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true +spring.flyway.clean-on-validation-error=true +spring.jpa.database=default + +# POSTGRES DATASOURCE +spring.datasource.jdbcUrl=jdbc:postgresql://localhost:5432/way +spring.datasource.username=postgres +spring.datasource.password=admin +spring.datasource.driver-class-name=org.postgresql.Driver + +# Solar Datasource +host.solr=http://localhost:8983/solr \ No newline at end of file diff --git a/src/test/java/br/com/zup/way/WayApplicationTests.java b/src/test/java/br/com/zup/way/WayApplicationTests.java new file mode 100644 index 00000000..3a00de64 --- /dev/null +++ b/src/test/java/br/com/zup/way/WayApplicationTests.java @@ -0,0 +1,17 @@ +package br.com.zup.way; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Profile; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class WayApplicationTests { + + @Test + public void contextLoads() { + } + +} From 39023610a71c2c0bf7b71b3dbaf9fc43a1e757c1 Mon Sep 17 00:00:00 2001 From: "warley.rocha" Date: Mon, 1 Jul 2019 15:28:40 +0100 Subject: [PATCH 2/9] =?UTF-8?q?Configura=C3=A7=C3=A3o=20do=20gitIgnore?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..a2a3040a --- /dev/null +++ b/.gitignore @@ -0,0 +1,31 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/** +!**/src/test/** + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ + +### VS Code ### +.vscode/ From e9c239c7e1f53e9c9462e848614de162fa0cf6a6 Mon Sep 17 00:00:00 2001 From: "warley.rocha" Date: Mon, 1 Jul 2019 15:32:59 +0100 Subject: [PATCH 3/9] =?UTF-8?q?Implementa=C3=A7=C3=A3o=20do=20banco=20post?= =?UTF-8?q?gres=20e=20solr?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 63 ++--- .../com/zup/way/FlywaySlaveInitializer.java | 27 ++ src/main/java/br/com/zup/way/WayDbConfig.java | 56 ++++ .../java/br/com/zup/way/WaySolrDbConfig.java | 35 +++ .../com/zup/way/db/postgres/model/Perfil.java | 29 ++ .../zup/way/db/postgres/model/Usuario.java | 67 +++++ .../way/db/postgres/model/dto/ErrorDTO.java | 15 ++ .../way/db/postgres/model/dto/LoginDTO.java | 20 ++ .../way/db/postgres/model/dto/TokenDTO.java | 14 + .../repository/UsuarioRepository.java | 13 + .../com/zup/way/db/solr/model/Categoria.java | 34 +++ .../br/com/zup/way/db/solr/model/Gasto.java | 46 ++++ .../way/db/solr/model/dto/CategoriaDTO.java | 27 ++ .../model/dto/FiltroCategorizarGastoDTO.java | 19 ++ .../way/db/solr/model/dto/FiltroGastoDTO.java | 20 ++ .../zup/way/db/solr/model/dto/GastoDTO.java | 43 +++ .../db/solr/model/dto/IntegrateGastoDTO.java | 25 ++ .../db/solr/repository/GastoRepository.java | 20 ++ .../resources/db/migration/V1__Create.sql | 54 ++++ .../resources/db/testdat/V1__CreateTest.sql | 19 ++ .../zup/way/EmbeddedWaySolrServerFactory.java | 71 +++++ .../java/br/com/zup/way/WaySolrDbConfig.java | 86 ++++++ .../GastoSolr/conf/lang/stopwords_en.txt | 54 ++++ .../GastoSolr/conf/lang/stopwords_pt.txt | 253 ++++++++++++++++++ .../configsets/GastoSolr/conf/params.json | 20 ++ .../configsets/GastoSolr/conf/protwords.txt | 21 ++ .../configsets/GastoSolr/conf/schema.xml | 147 ++++++++++ .../configsets/GastoSolr/conf/solrconfig.xml | 44 +++ .../configsets/GastoSolr/conf/stopwords.txt | 14 + .../configsets/GastoSolr/conf/synonyms.txt | 29 ++ 30 files changed, 1347 insertions(+), 38 deletions(-) create mode 100644 src/main/java/br/com/zup/way/FlywaySlaveInitializer.java create mode 100644 src/main/java/br/com/zup/way/WayDbConfig.java create mode 100644 src/main/java/br/com/zup/way/WaySolrDbConfig.java create mode 100644 src/main/java/br/com/zup/way/db/postgres/model/Perfil.java create mode 100644 src/main/java/br/com/zup/way/db/postgres/model/Usuario.java create mode 100644 src/main/java/br/com/zup/way/db/postgres/model/dto/ErrorDTO.java create mode 100644 src/main/java/br/com/zup/way/db/postgres/model/dto/LoginDTO.java create mode 100644 src/main/java/br/com/zup/way/db/postgres/model/dto/TokenDTO.java create mode 100644 src/main/java/br/com/zup/way/db/postgres/repository/UsuarioRepository.java create mode 100644 src/main/java/br/com/zup/way/db/solr/model/Categoria.java create mode 100644 src/main/java/br/com/zup/way/db/solr/model/Gasto.java create mode 100644 src/main/java/br/com/zup/way/db/solr/model/dto/CategoriaDTO.java create mode 100644 src/main/java/br/com/zup/way/db/solr/model/dto/FiltroCategorizarGastoDTO.java create mode 100644 src/main/java/br/com/zup/way/db/solr/model/dto/FiltroGastoDTO.java create mode 100644 src/main/java/br/com/zup/way/db/solr/model/dto/GastoDTO.java create mode 100644 src/main/java/br/com/zup/way/db/solr/model/dto/IntegrateGastoDTO.java create mode 100644 src/main/java/br/com/zup/way/db/solr/repository/GastoRepository.java create mode 100644 src/main/resources/db/migration/V1__Create.sql create mode 100644 src/main/resources/db/testdat/V1__CreateTest.sql create mode 100644 src/test/java/br/com/zup/way/EmbeddedWaySolrServerFactory.java create mode 100644 src/test/java/br/com/zup/way/WaySolrDbConfig.java create mode 100644 src/test/resources/configsets/GastoSolr/conf/lang/stopwords_en.txt create mode 100644 src/test/resources/configsets/GastoSolr/conf/lang/stopwords_pt.txt create mode 100644 src/test/resources/configsets/GastoSolr/conf/params.json create mode 100644 src/test/resources/configsets/GastoSolr/conf/protwords.txt create mode 100644 src/test/resources/configsets/GastoSolr/conf/schema.xml create mode 100644 src/test/resources/configsets/GastoSolr/conf/solrconfig.xml create mode 100644 src/test/resources/configsets/GastoSolr/conf/stopwords.txt create mode 100644 src/test/resources/configsets/GastoSolr/conf/synonyms.txt diff --git a/pom.xml b/pom.xml index 7c7768f6..4e660af2 100644 --- a/pom.xml +++ b/pom.xml @@ -52,14 +52,14 @@ - io.dropwizard.metrics - metrics-core - 3.2.6 + org.springframework.boot + spring-boot-starter-web org.springframework.boot - spring-boot-starter-web + spring-boot-starter-test + test @@ -69,24 +69,6 @@ true - - org.projectlombok - lombok - true - - - - org.mapstruct - mapstruct - ${org.mapstruct.version} - - - - org.springframework.boot - spring-boot-starter-test - test - - org.springframework.security spring-security-test @@ -94,9 +76,9 @@ - io.springfox - springfox-swagger2 - 2.9.2 + org.springframework.security + spring-security-jwt + ${jwt.version} @@ -119,17 +101,28 @@ spring-data-solr - - org.springframework.security.oauth - spring-security-oauth2 - ${oauth.version} + org.projectlombok + lombok + true - org.springframework.security - spring-security-jwt - ${jwt.version} + io.dropwizard.metrics + metrics-core + 3.2.6 + + + + org.mapstruct + mapstruct + ${org.mapstruct.version} + + + + io.springfox + springfox-swagger2 + 2.9.2 @@ -174,12 +167,6 @@ 5.2.4 - - com.h2database - h2 - runtime - - io.jsonwebtoken jjwt diff --git a/src/main/java/br/com/zup/way/FlywaySlaveInitializer.java b/src/main/java/br/com/zup/way/FlywaySlaveInitializer.java new file mode 100644 index 00000000..38b55ccc --- /dev/null +++ b/src/main/java/br/com/zup/way/FlywaySlaveInitializer.java @@ -0,0 +1,27 @@ +package br.com.zup.way; + +import org.flywaydb.core.Flyway; +import org.springframework.context.annotation.Configuration; + +import javax.annotation.PostConstruct; +import javax.sql.DataSource; + +@Configuration +public class FlywaySlaveInitializer { + + private DataSource dataSource; + + public FlywaySlaveInitializer(DataSource dataSource) { + this.dataSource = dataSource; + } + + @PostConstruct + public void migrateFlyway() { + Flyway flyway = new Flyway(); + + flyway.setDataSource(dataSource); + flyway.setLocations("db/migration"); + flyway.migrate(); + + } +} diff --git a/src/main/java/br/com/zup/way/WayDbConfig.java b/src/main/java/br/com/zup/way/WayDbConfig.java new file mode 100644 index 00000000..036ccac5 --- /dev/null +++ b/src/main/java/br/com/zup/way/WayDbConfig.java @@ -0,0 +1,56 @@ +package br.com.zup.way; + +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.jdbc.DataSourceBuilder; +import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import javax.persistence.EntityManagerFactory; +import javax.sql.DataSource; + +@Configuration +@EnableTransactionManagement +@EnableJpaRepositories( + entityManagerFactoryRef = "entityManagerFactory", + basePackages = {"br.com.zup.way.db.postgres.repository"} +) +public class WayDbConfig { + + @Primary + @Bean(name = "dataSource") + @ConfigurationProperties(prefix = "spring.datasource") + public DataSource dataSource() { + return DataSourceBuilder.create().build(); + } + + @Primary + @Bean(name = "entityManagerFactory") + public LocalContainerEntityManagerFactoryBean + entityManagerFactory( + EntityManagerFactoryBuilder builder, + @Qualifier("dataSource") DataSource dataSource + ) { + return builder + .dataSource(dataSource) + .packages("br.com.zup.way.db.postgres.model") + .persistenceUnit("way") + .build(); + } + + @Primary + @Bean(name = "transactionManager") + public PlatformTransactionManager transactionManager( + @Qualifier("entityManagerFactory") EntityManagerFactory + entityManagerFactory + ) { + return new JpaTransactionManager(entityManagerFactory); + } +} diff --git a/src/main/java/br/com/zup/way/WaySolrDbConfig.java b/src/main/java/br/com/zup/way/WaySolrDbConfig.java new file mode 100644 index 00000000..c92f45b8 --- /dev/null +++ b/src/main/java/br/com/zup/way/WaySolrDbConfig.java @@ -0,0 +1,35 @@ +package br.com.zup.way; + +import org.apache.solr.client.solrj.SolrClient; +import org.apache.solr.client.solrj.impl.HttpSolrClient; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import org.springframework.data.solr.core.SolrTemplate; +import org.springframework.data.solr.repository.config.EnableSolrRepositories; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +@Configuration +@EnableTransactionManagement +@EnableSolrRepositories(basePackages = "br.com.zup.way.db.solr.repository") +@ComponentScan +@Profile("dev") +public class WaySolrDbConfig { + + static final String CONFIGSET_DIR = "src/test/resources/configsets"; + + @Value("${host.solr}") + private String hostSolr; + + @Bean + public SolrClient solrClient() { + return new HttpSolrClient.Builder().withBaseSolrUrl(hostSolr).build(); + } + + @Bean + public SolrTemplate solrTemplate(SolrClient client) { + return new SolrTemplate(client); + } +} \ No newline at end of file diff --git a/src/main/java/br/com/zup/way/db/postgres/model/Perfil.java b/src/main/java/br/com/zup/way/db/postgres/model/Perfil.java new file mode 100644 index 00000000..0a6411a7 --- /dev/null +++ b/src/main/java/br/com/zup/way/db/postgres/model/Perfil.java @@ -0,0 +1,29 @@ +package br.com.zup.way.db.postgres.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.security.core.GrantedAuthority; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +@Entity +@Data +@AllArgsConstructor +@NoArgsConstructor +class Perfil implements GrantedAuthority { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String nome; + + @Override + public String getAuthority() { + return this.nome; + } +} diff --git a/src/main/java/br/com/zup/way/db/postgres/model/Usuario.java b/src/main/java/br/com/zup/way/db/postgres/model/Usuario.java new file mode 100644 index 00000000..cfaa3711 --- /dev/null +++ b/src/main/java/br/com/zup/way/db/postgres/model/Usuario.java @@ -0,0 +1,67 @@ +package br.com.zup.way.db.postgres.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import javax.persistence.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +@Entity +@Data +@NoArgsConstructor +@AllArgsConstructor +public class Usuario implements UserDetails { + + + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + private String nome; + private String login; + private String senha; + + private Integer tipo; + + @ManyToMany(fetch = FetchType.EAGER) + private List perfis = new ArrayList(); + + @Override + public Collection getAuthorities() { + return this.perfis; + } + + @Override + public String getPassword() { + return this.senha; + } + + @Override + public String getUsername() { + return this.login; + } + + @Override + public boolean isAccountNonExpired() { + return true; + } + + @Override + public boolean isAccountNonLocked() { + return true; + } + + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + @Override + public boolean isEnabled() { + return true; + } + +} diff --git a/src/main/java/br/com/zup/way/db/postgres/model/dto/ErrorDTO.java b/src/main/java/br/com/zup/way/db/postgres/model/dto/ErrorDTO.java new file mode 100644 index 00000000..55e4d5d6 --- /dev/null +++ b/src/main/java/br/com/zup/way/db/postgres/model/dto/ErrorDTO.java @@ -0,0 +1,15 @@ +package br.com.zup.way.db.postgres.model.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class ErrorDTO { + + private String field; + private String error; + +} \ No newline at end of file diff --git a/src/main/java/br/com/zup/way/db/postgres/model/dto/LoginDTO.java b/src/main/java/br/com/zup/way/db/postgres/model/dto/LoginDTO.java new file mode 100644 index 00000000..4a690feb --- /dev/null +++ b/src/main/java/br/com/zup/way/db/postgres/model/dto/LoginDTO.java @@ -0,0 +1,20 @@ +package br.com.zup.way.db.postgres.model.dto; + +import lombok.Data; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; + +import javax.validation.constraints.NotNull; + +@Data +public class LoginDTO { + + @NotNull + private String login; + + @NotNull + private String senha; + + public UsernamePasswordAuthenticationToken converter() { + return new UsernamePasswordAuthenticationToken(login, senha); + } +} diff --git a/src/main/java/br/com/zup/way/db/postgres/model/dto/TokenDTO.java b/src/main/java/br/com/zup/way/db/postgres/model/dto/TokenDTO.java new file mode 100644 index 00000000..31572896 --- /dev/null +++ b/src/main/java/br/com/zup/way/db/postgres/model/dto/TokenDTO.java @@ -0,0 +1,14 @@ +package br.com.zup.way.db.postgres.model.dto; + +import lombok.Getter; + +@Getter +public class TokenDTO { + private String token; + private String type; + + public TokenDTO(String token, String type) { + this.token = token; + this.type = type; + } +} diff --git a/src/main/java/br/com/zup/way/db/postgres/repository/UsuarioRepository.java b/src/main/java/br/com/zup/way/db/postgres/repository/UsuarioRepository.java new file mode 100644 index 00000000..ae69479b --- /dev/null +++ b/src/main/java/br/com/zup/way/db/postgres/repository/UsuarioRepository.java @@ -0,0 +1,13 @@ +package br.com.zup.way.db.postgres.repository; + +import br.com.zup.way.db.postgres.model.Usuario; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface UsuarioRepository extends JpaRepository { + + Optional findByLogin(String login); + + Optional findByIdAndTipo(Long codUsuario, Integer tipo); +} diff --git a/src/main/java/br/com/zup/way/db/solr/model/Categoria.java b/src/main/java/br/com/zup/way/db/solr/model/Categoria.java new file mode 100644 index 00000000..ce0fc1b7 --- /dev/null +++ b/src/main/java/br/com/zup/way/db/solr/model/Categoria.java @@ -0,0 +1,34 @@ +package br.com.zup.way.db.solr.model; + +import br.com.zup.way.db.solr.model.dto.CategoriaDTO; +import br.com.zup.way.util.mapper.CategoriaMapper; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.apache.solr.client.solrj.beans.Field; +import org.springframework.data.solr.core.mapping.SolrDocument; + +import javax.persistence.Entity; +import javax.persistence.Id; + +@Entity +@Data +@AllArgsConstructor +@NoArgsConstructor +@SolrDocument(collection = "CategoriaSolr") +public class Categoria { + + @Id + @Field + private String id; + + @Field("nome_text_pt") + private String nome; + + @Field + private Long codigoUsuario; + + public static Categoria convert(CategoriaDTO categoriaDTO) { + return CategoriaMapper.INSTANCE.categoriaDTOtoCategoria(categoriaDTO); + } +} diff --git a/src/main/java/br/com/zup/way/db/solr/model/Gasto.java b/src/main/java/br/com/zup/way/db/solr/model/Gasto.java new file mode 100644 index 00000000..c1131a47 --- /dev/null +++ b/src/main/java/br/com/zup/way/db/solr/model/Gasto.java @@ -0,0 +1,46 @@ +package br.com.zup.way.db.solr.model; + +import br.com.zup.way.db.solr.model.dto.GastoDTO; +import br.com.zup.way.db.solr.model.dto.IntegrateGastoDTO; +import br.com.zup.way.util.mapper.GastoMapper; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.apache.solr.client.solrj.beans.Field; +import org.springframework.data.solr.core.mapping.SolrDocument; + +import javax.persistence.Entity; +import javax.persistence.Id; +import java.time.LocalDateTime; + +@Entity +@Data +@AllArgsConstructor +@NoArgsConstructor +@SolrDocument(collection = "GastoSolr") +public class Gasto { + + @Id + @Field + private String id; + + @Field("descricao_text_pt") + private String descricao; + + @Field + private Double valor; + + @Field + private Long codigoUsuario; + + @Field("categoria_text_pt") + private String categoria; + + @Field("data_cadastro_dt") + private LocalDateTime dataCadastro; + + public static Gasto convert(IntegrateGastoDTO gastoDTO) { + return GastoMapper.INSTANCE.gastoDTOtoGasto(gastoDTO); + } + +} diff --git a/src/main/java/br/com/zup/way/db/solr/model/dto/CategoriaDTO.java b/src/main/java/br/com/zup/way/db/solr/model/dto/CategoriaDTO.java new file mode 100644 index 00000000..5962b20d --- /dev/null +++ b/src/main/java/br/com/zup/way/db/solr/model/dto/CategoriaDTO.java @@ -0,0 +1,27 @@ +package br.com.zup.way.db.solr.model.dto; + +import br.com.zup.way.db.solr.model.Categoria; +import br.com.zup.way.util.mapper.CategoriaMapper; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class CategoriaDTO { + + private String nome; + + private Long codigoUsuario; + + public static List convert(List categorias) { + return CategoriaMapper.INSTANCE.categoriaToCategoriaDTO(categorias); + } + + public static CategoriaDTO convert(Categoria categoria) { + return CategoriaMapper.INSTANCE.categoriaToCategoriaDTO(categoria); + } +} diff --git a/src/main/java/br/com/zup/way/db/solr/model/dto/FiltroCategorizarGastoDTO.java b/src/main/java/br/com/zup/way/db/solr/model/dto/FiltroCategorizarGastoDTO.java new file mode 100644 index 00000000..60c6d57c --- /dev/null +++ b/src/main/java/br/com/zup/way/db/solr/model/dto/FiltroCategorizarGastoDTO.java @@ -0,0 +1,19 @@ +package br.com.zup.way.db.solr.model.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class FiltroCategorizarGastoDTO { + + @NotNull + private String categoria; + + @NotNull + private String idGasto; +} diff --git a/src/main/java/br/com/zup/way/db/solr/model/dto/FiltroGastoDTO.java b/src/main/java/br/com/zup/way/db/solr/model/dto/FiltroGastoDTO.java new file mode 100644 index 00000000..38aa0b6a --- /dev/null +++ b/src/main/java/br/com/zup/way/db/solr/model/dto/FiltroGastoDTO.java @@ -0,0 +1,20 @@ +package br.com.zup.way.db.solr.model.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class FiltroGastoDTO { + + @NotNull + @DateTimeFormat(pattern = "dd/MM/yyyy") + private LocalDateTime filtroData; +} diff --git a/src/main/java/br/com/zup/way/db/solr/model/dto/GastoDTO.java b/src/main/java/br/com/zup/way/db/solr/model/dto/GastoDTO.java new file mode 100644 index 00000000..e66b1dfe --- /dev/null +++ b/src/main/java/br/com/zup/way/db/solr/model/dto/GastoDTO.java @@ -0,0 +1,43 @@ +package br.com.zup.way.db.solr.model.dto; + +import br.com.zup.way.db.solr.model.Gasto; +import br.com.zup.way.util.mapper.GastoMapper; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; +import java.util.List; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(exclude = "id") +public class GastoDTO { + + private String id; + + @NotNull + private String descricao; + + @NotNull + private Double valor; + + @NotNull + private Long codigoUsuario; + + private LocalDateTime dataCadastro; + + private String categoria; + + public static GastoDTO convert(Gasto gasto) { + return GastoMapper.INSTANCE.gastoToGastoDTO(gasto); + } + + public static List convert(List gasto) { + return GastoMapper.INSTANCE.gastoToGastoDTO(gasto); + } + +} diff --git a/src/main/java/br/com/zup/way/db/solr/model/dto/IntegrateGastoDTO.java b/src/main/java/br/com/zup/way/db/solr/model/dto/IntegrateGastoDTO.java new file mode 100644 index 00000000..27ee9810 --- /dev/null +++ b/src/main/java/br/com/zup/way/db/solr/model/dto/IntegrateGastoDTO.java @@ -0,0 +1,25 @@ +package br.com.zup.way.db.solr.model.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class IntegrateGastoDTO { + + @NotNull + private Long codigoUsuario; + + @NotNull + private String descricao; + + @NotNull + private Double valor; + + private LocalDateTime dataCadastro; +} diff --git a/src/main/java/br/com/zup/way/db/solr/repository/GastoRepository.java b/src/main/java/br/com/zup/way/db/solr/repository/GastoRepository.java new file mode 100644 index 00000000..c1f17d35 --- /dev/null +++ b/src/main/java/br/com/zup/way/db/solr/repository/GastoRepository.java @@ -0,0 +1,20 @@ +package br.com.zup.way.db.solr.repository; + +import br.com.zup.way.db.solr.model.Gasto; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; +import org.springframework.data.solr.repository.SolrCrudRepository; + +import java.util.List; + +public interface GastoRepository extends SolrCrudRepository { + + List findGastoByDescricaoIgnoreCaseAndCodigoUsuario(String descricao, Long codigoUsuario); + + List findGastoByCodigoUsuarioAndDataCadastroLessThanEqual(Long codigoUsuario, String dataLimite, PageRequest dataCadastro); + + List findGastoByCodigoUsuarioAndDataCadastroBetween(Long codigoUsuario, String dataLimiteInicio, String dataLimiteFim, Sort dataCadastro); + + List findGastoByCategoriaContainingIgnoreCaseAndCodigoUsuarioOrderByCategoria(String nomeCategoria, Long codigoUsuario); + +} diff --git a/src/main/resources/db/migration/V1__Create.sql b/src/main/resources/db/migration/V1__Create.sql new file mode 100644 index 00000000..ab444ca1 --- /dev/null +++ b/src/main/resources/db/migration/V1__Create.sql @@ -0,0 +1,54 @@ +CREATE TABLE "usuario" +( + "id" SERIAL NOT NULL, + "nome" TEXT NOT NULL, + "login" TEXT NOT NULL, + "senha" TEXT NOT NULL, + "tipo" INTEGER NOT NULL, + CONSTRAINT usuario_pk PRIMARY KEY ("id") +) WITH ( + OIDS=FALSE +); + +CREATE TABLE "perfil" +( + "id" SERIAL NOT NULL, + "nome" TEXT NOT NULL, + CONSTRAINT perfil_pk PRIMARY KEY ("id") +) WITH ( + OIDS=FALSE +); + +CREATE TABLE "usuario_perfil" +( + "usuario_id" SERIAL NOT NULL, + "perfis_id" SERIAL NOT NULL, + FOREIGN KEY (usuario_id) REFERENCES "usuario" (id), + FOREIGN KEY ("perfis_id") REFERENCES "perfil" (id) +) WITH ( + OIDS=FALSE +); + +CREATE TABLE "categoria" +( + "id" SERIAL NOT NULL, + "nome" TEXT NOT NULL, + CONSTRAINT categoria_pk PRIMARY KEY ("id") +) WITH ( + OIDS=FALSE +); + +INSERT INTO "perfil" ("nome") VALUES ( 'ROLE_ADMIN'); +INSERT INTO "perfil" ("nome") VALUES ( 'ROLE_USER'); +INSERT INTO "perfil" ("nome") VALUES ( 'ROLE_SYS'); + +INSERT INTO "usuario" ("nome", "login", "senha", "tipo") VALUES ( 'Administrador','admin','$2a$10$.ltOnHeuxrc2JLpiG8Ex0.1MT/L2Ah2faemk6DCR.yZAhK6yt2fve',2); +INSERT INTO "usuario" ("nome", "login", "senha", "tipo") VALUES ( 'Usuario','user','$2a$10$oLSlGuWbD43fYrw.7DzkQubr2Q8Ronbnw8r1zpkjTHzJsQ6z5oXPq',1); +INSERT INTO "usuario" ("nome", "login", "senha", "tipo") VALUES ( 'Sistema','sys','$2a$10$opBp5R5Cvje.VC/jwNTuLOucdUbKpue9kEzA5gSdYEYzZ6Eb/M.Cq',2); + + +INSERT INTO "usuario_perfil" ("usuario_id","perfis_id") VALUES (1,1); +INSERT INTO "usuario_perfil" ("usuario_id","perfis_id") VALUES (2,2); +INSERT INTO "usuario_perfil" ("usuario_id","perfis_id") VALUES (3,3); + + diff --git a/src/main/resources/db/testdat/V1__CreateTest.sql b/src/main/resources/db/testdat/V1__CreateTest.sql new file mode 100644 index 00000000..dffe16b5 --- /dev/null +++ b/src/main/resources/db/testdat/V1__CreateTest.sql @@ -0,0 +1,19 @@ +CREATE TABLE "USUARIO" +( + "ID" BIGINT AUTO_INCREMENT PRIMARY KEY, + "NOME" TEXT NOT NULL, + "LOGIN" TEXT NOT NULL, + "SENHA" TEXT NOT NULL, + "TIPO" INTEGER NOT NULL, +); + +CREATE TABLE "PERFIL" +( + "ID" BIGINT AUTO_INCREMENT PRIMARY KEY, + "NOME" TEXT NOT NULL +); + + +INSERT INTO "USUARIO" ("NOME", "LOGIN", "SENHA", "TIPO") VALUES ( 'Administrador','admin','$2a$10$.ltOnHeuxrc2JLpiG8Ex0.1MT/L2Ah2faemk6DCR.yZAhK6yt2fve',1); +INSERT INTO "USUARIO" ("NOME", "LOGIN", "SENHA", "TIPO") VALUES ( 'Usuario','user','$2a$10$oLSlGuWbD43fYrw.7DzkQubr2Q8Ronbnw8r1zpkjTHzJsQ6z5oXPq',2); +INSERT INTO "USUARIO" ("NOME", "LOGIN", "SENHA", "TIPO") VALUES ( 'Sistema','sys','$2a$10$opBp5R5Cvje.VC/jwNTuLOucdUbKpue9kEzA5gSdYEYzZ6Eb/M.Cq',1); diff --git a/src/test/java/br/com/zup/way/EmbeddedWaySolrServerFactory.java b/src/test/java/br/com/zup/way/EmbeddedWaySolrServerFactory.java new file mode 100644 index 00000000..2e03e47b --- /dev/null +++ b/src/test/java/br/com/zup/way/EmbeddedWaySolrServerFactory.java @@ -0,0 +1,71 @@ +package br.com.zup.way; + +import org.apache.commons.io.FileUtils; +import org.apache.solr.client.solrj.SolrClient; +import org.apache.solr.client.solrj.SolrServerException; +import org.apache.solr.client.solrj.embedded.EmbeddedSolrServer; +import org.apache.solr.client.solrj.request.CoreAdminRequest; +import org.apache.solr.core.NodeConfig; +import org.apache.solr.core.SolrResourceLoader; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; + +/** + * @author bbende + */ +public class EmbeddedWaySolrServerFactory { + + /** + * Cleans the given solrHome directory and creates a new EmbeddedSolrServer. + * + * @param solrHome the Solr home directory to use + * @param configSetHome the directory containing config sets + * @param coreName the name of the core, must have a matching directory in configHome + * @return an EmbeddedSolrServer with a core created for the given coreName + * @throws IOException + */ + public static SolrClient create(final String solrHome, final String configSetHome, final String coreName) + throws IOException, SolrServerException { + return create(solrHome, configSetHome, coreName, true); + } + + /** + * @param solrHome the Solr home directory to use + * @param configSetHome the directory containing config sets + * @param coreName the name of the core, must have a matching directory in configHome + * @param cleanSolrHome if true the directory for solrHome will be deleted and re-created if it already exists + * @return an EmbeddedSolrServer with a core created for the given coreName + * @throws IOException + */ + public static SolrClient create(final String solrHome, final String configSetHome, final String coreName, final boolean cleanSolrHome) + throws IOException, SolrServerException { + + final File solrHomeDir = new File(solrHome); + if (solrHomeDir.exists()) { + FileUtils.deleteDirectory(solrHomeDir); + solrHomeDir.mkdirs(); + } else { + solrHomeDir.mkdirs(); + } + + final SolrResourceLoader loader = new SolrResourceLoader(solrHomeDir.toPath()); + final Path configSetPath = Paths.get(configSetHome).toAbsolutePath(); + + final NodeConfig config = new NodeConfig.NodeConfigBuilder("embeddedSolrServerNode", loader) + .setConfigSetBaseDirectory(configSetPath.toString()) + .build(); + + final EmbeddedSolrServer embeddedSolrServer = new EmbeddedSolrServer(config, coreName); + + final CoreAdminRequest.Create createRequest = new CoreAdminRequest.Create(); + createRequest.setCoreName(coreName); + createRequest.setConfigSet(coreName); + embeddedSolrServer.request(createRequest); + + return embeddedSolrServer; + } + +} diff --git a/src/test/java/br/com/zup/way/WaySolrDbConfig.java b/src/test/java/br/com/zup/way/WaySolrDbConfig.java new file mode 100644 index 00000000..c05f3991 --- /dev/null +++ b/src/test/java/br/com/zup/way/WaySolrDbConfig.java @@ -0,0 +1,86 @@ +package br.com.zup.way; + +import br.com.zup.way.util.DateUtil; +import org.apache.solr.client.solrj.SolrClient; +import org.apache.solr.client.solrj.SolrServerException; +import org.apache.solr.common.SolrInputDocument; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import org.springframework.data.solr.core.SolrTemplate; +import org.springframework.data.solr.repository.config.EnableSolrRepositories; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import java.io.IOException; +import java.time.LocalDateTime; +import java.util.Arrays; + +@Configuration +@EnableTransactionManagement +@EnableSolrRepositories(basePackages = "br.com.zup.way.db.solr.repository") +@ComponentScan +@Profile("test") +public class WaySolrDbConfig { + + static final String CONFIGSET_DIR = "src/test/resources/configsets"; + + private LocalDateTime dataCadastro = DateUtil.setZone(LocalDateTime.of(2019, 01, 01, 8, 00)); + + @Bean + public SolrClient solrClient() { + return getEmbeddedSolr(); + } + + private SolrClient getEmbeddedSolr() { + String targetLocation = EmbeddedWaySolrServerFactory.class + .getProtectionDomain().getCodeSource().getLocation().getFile() + "/.."; + + String solrHome = targetLocation + "/solr"; + + try { + SolrClient solrClient = EmbeddedWaySolrServerFactory.create(solrHome, CONFIGSET_DIR, "GastoSolr"); + + LocalDateTime dataCadastro = DateUtil.setZone(LocalDateTime.of(2019, 01, 01, 8, 00)); + + SolrInputDocument doc1 = new SolrInputDocument(); + + doc1.setField("id", "513b08d9-b286-4da4-a09f-33d15687e972"); + doc1.addField("descricao_text_pt", "TAM SITE"); + doc1.addField("valor", 300); + doc1.addField("codigoUsuario", 2); + doc1.addField("data_cadastro_dt", DateUtil.format(dataCadastro)); + + SolrInputDocument doc2 = new SolrInputDocument(); + + doc2.addField("descricao_text_pt", "Padaria No Céu"); + doc2.addField("valor", 50D); + doc2.addField("codigoUsuario", 2); + doc2.addField("categoria_text_pt", "Restaurante"); + doc2.addField("data_cadastro_dt", DateUtil.format(dataCadastro)); + + SolrInputDocument doc3 = new SolrInputDocument(); + + doc3.addField("descricao_text_pt", "Uber Do Brasil"); + doc3.addField("valor", 10D); + doc3.addField("codigoUsuario", 2); + doc3.addField("categoria_text_pt", "Transporte"); + doc3.addField("data_cadastro_dt", DateUtil.format(dataCadastro)); + + solrClient.add(Arrays.asList(doc1, doc2, doc3)); + solrClient.commit(); + return solrClient; + } catch (IOException e) { + e.printStackTrace(); + } catch (SolrServerException e) { + e.printStackTrace(); + } + return null; + } + + + @Bean + public SolrTemplate solrTemplate(SolrClient client) { + return new SolrTemplate(client); + } +} \ No newline at end of file diff --git a/src/test/resources/configsets/GastoSolr/conf/lang/stopwords_en.txt b/src/test/resources/configsets/GastoSolr/conf/lang/stopwords_en.txt new file mode 100644 index 00000000..2c164c0b --- /dev/null +++ b/src/test/resources/configsets/GastoSolr/conf/lang/stopwords_en.txt @@ -0,0 +1,54 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# a couple of test stopwords to test that the words are really being +# configured from this file: +stopworda +stopwordb + +# Standard english stop words taken from Lucene's StopAnalyzer +a +an +and +are +as +at +be +but +by +for +if +in +into +is +it +no +not +of +on +or +such +that +the +their +then +there +these +they +this +to +was +will +with diff --git a/src/test/resources/configsets/GastoSolr/conf/lang/stopwords_pt.txt b/src/test/resources/configsets/GastoSolr/conf/lang/stopwords_pt.txt new file mode 100644 index 00000000..acfeb01a --- /dev/null +++ b/src/test/resources/configsets/GastoSolr/conf/lang/stopwords_pt.txt @@ -0,0 +1,253 @@ + | From svn.tartarus.org/snowball/trunk/website/algorithms/portuguese/stop.txt + | This file is distributed under the BSD License. + | See http://snowball.tartarus.org/license.php + | Also see http://www.opensource.org/licenses/bsd-license.html + | - Encoding was converted to UTF-8. + | - This notice was added. + | + | NOTE: To use this file with StopFilterFactory, you must specify format="snowball" + + | A Portuguese stop word list. Comments begin with vertical bar. Each stop + | word is at the start of a line. + + + | The following is a ranked list (commonest to rarest) of stopwords + | deriving from a large sample of text. + + | Extra words have been added at the end. + +de | of, from +a | the; to, at; her +o | the; him +que | who, that +e | and +do | de + o +da | de + a +em | in +um | a +para | for + | é from SER +com | with +não | not, no +uma | a +os | the; them +no | em + o +se | himself etc +na | em + a +por | for +mais | more +as | the; them +dos | de + os +como | as, like +mas | but + | foi from SER +ao | a + o +ele | he +das | de + as + | tem from TER +à | a + a +seu | his +sua | her +ou | or + | ser from SER +quando | when +muito | much + | há from HAV +nos | em + os; us +já | already, now + | está from EST +eu | I +também | also +só | only, just +pelo | per + o +pela | per + a +até | up to +isso | that +ela | he +entre | between + | era from SER +depois | after +sem | without +mesmo | same +aos | a + os + | ter from TER +seus | his +quem | whom +nas | em + as +me | me +esse | that +eles | they + | estão from EST +você | you + | tinha from TER + | foram from SER +essa | that +num | em + um +nem | nor +suas | her +meu | my +às | a + as +minha | my + | têm from TER +numa | em + uma +pelos | per + os +elas | they + | havia from HAV + | seja from SER +qual | which + | será from SER +nós | we + | tenho from TER +lhe | to him, her +deles | of them +essas | those +esses | those +pelas | per + as +este | this + | fosse from SER +dele | of him + + | other words. There are many contractions such as naquele = em+aquele, + | mo = me+o, but they are rare. + | Indefinite article plural forms are also rare. + +tu | thou +te | thee +vocês | you (plural) +vos | you +lhes | to them +meus | my +minhas +teu | thy +tua +teus +tuas +nosso | our +nossa +nossos +nossas + +dela | of her +delas | of them + +esta | this +estes | these +estas | these +aquele | that +aquela | that +aqueles | those +aquelas | those +isto | this +aquilo | that + + | forms of estar, to be (not including the infinitive): +estou +está +estamos +estão +estive +esteve +estivemos +estiveram +estava +estávamos +estavam +estivera +estivéramos +esteja +estejamos +estejam +estivesse +estivéssemos +estivessem +estiver +estivermos +estiverem + + | forms of haver, to have (not including the infinitive): +hei +há +havemos +hão +houve +houvemos +houveram +houvera +houvéramos +haja +hajamos +hajam +houvesse +houvéssemos +houvessem +houver +houvermos +houverem +houverei +houverá +houveremos +houverão +houveria +houveríamos +houveriam + + | forms of ser, to be (not including the infinitive): +sou +somos +são +era +éramos +eram +fui +foi +fomos +foram +fora +fôramos +seja +sejamos +sejam +fosse +fôssemos +fossem +for +formos +forem +serei +será +seremos +serão +seria +seríamos +seriam + + | forms of ter, to have (not including the infinitive): +tenho +tem +temos +tém +tinha +tínhamos +tinham +tive +teve +tivemos +tiveram +tivera +tivéramos +tenha +tenhamos +tenham +tivesse +tivéssemos +tivessem +tiver +tivermos +tiverem +terei +terá +teremos +terão +teria +teríamos +teriam diff --git a/src/test/resources/configsets/GastoSolr/conf/params.json b/src/test/resources/configsets/GastoSolr/conf/params.json new file mode 100644 index 00000000..06114ef2 --- /dev/null +++ b/src/test/resources/configsets/GastoSolr/conf/params.json @@ -0,0 +1,20 @@ +{"params":{ + "query":{ + "defType":"edismax", + "q.alt":"*:*", + "rows":"10", + "fl":"*,score", + "":{"v":0} + }, + "facets":{ + "facet":"on", + "facet.mincount": "1", + "":{"v":0} + }, + "velocity":{ + "wt": "velocity", + "v.template":"browse", + "v.layout": "layout", + "":{"v":0} + } +}} \ No newline at end of file diff --git a/src/test/resources/configsets/GastoSolr/conf/protwords.txt b/src/test/resources/configsets/GastoSolr/conf/protwords.txt new file mode 100644 index 00000000..1dfc0abe --- /dev/null +++ b/src/test/resources/configsets/GastoSolr/conf/protwords.txt @@ -0,0 +1,21 @@ +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#----------------------------------------------------------------------- +# Use a protected word file to protect against the stemmer reducing two +# unrelated words to the same base word. + +# Some non-words that normally won't be encountered, +# just to test that they won't be stemmed. +dontstems +zwhacky + diff --git a/src/test/resources/configsets/GastoSolr/conf/schema.xml b/src/test/resources/configsets/GastoSolr/conf/schema.xml new file mode 100644 index 00000000..93115691 --- /dev/null +++ b/src/test/resources/configsets/GastoSolr/conf/schema.xml @@ -0,0 +1,147 @@ + + + + + + + + + + + + + + id + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/resources/configsets/GastoSolr/conf/solrconfig.xml b/src/test/resources/configsets/GastoSolr/conf/solrconfig.xml new file mode 100644 index 00000000..fcfb9bb3 --- /dev/null +++ b/src/test/resources/configsets/GastoSolr/conf/solrconfig.xml @@ -0,0 +1,44 @@ + + + + 6.2.1 + + ${solr.data.dir:} + + + + + single + + + + + + + + + + + + id + + + + + + \ No newline at end of file diff --git a/src/test/resources/configsets/GastoSolr/conf/stopwords.txt b/src/test/resources/configsets/GastoSolr/conf/stopwords.txt new file mode 100644 index 00000000..ae1e83ee --- /dev/null +++ b/src/test/resources/configsets/GastoSolr/conf/stopwords.txt @@ -0,0 +1,14 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/src/test/resources/configsets/GastoSolr/conf/synonyms.txt b/src/test/resources/configsets/GastoSolr/conf/synonyms.txt new file mode 100644 index 00000000..7f721283 --- /dev/null +++ b/src/test/resources/configsets/GastoSolr/conf/synonyms.txt @@ -0,0 +1,29 @@ +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#----------------------------------------------------------------------- +#some test synonym mappings unlikely to appear in real input text +aaafoo => aaabar +bbbfoo => bbbfoo bbbbar +cccfoo => cccbar cccbaz +fooaaa,baraaa,bazaaa + +# Some synonym groups specific to this example +GB,gib,gigabyte,gigabytes +MB,mib,megabyte,megabytes +Television, Televisions, TV, TVs +#notice we use "gib" instead of "GiB" so any WordDelimiterFilter coming +#after us won't split it into two words. + +# Synonym mappings can be used for spelling correction too +pixima => pixma + From db3f79d2dad5a6451f6435cb8896b777306f8bf9 Mon Sep 17 00:00:00 2001 From: "warley.rocha" Date: Mon, 1 Jul 2019 15:35:12 +0100 Subject: [PATCH 4/9] =?UTF-8?q?Implementa=C3=A7=C3=A3o=20dos=20utilitarios?= =?UTF-8?q?=20Mapper=20Swagger=20Date=20Business?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/br/com/zup/way/util/DateUtil.java | 29 +++++++++++ .../util/Exception/WayBusinessException.java | 11 ++++ .../zup/way/util/mapper/CategoriaMapper.java | 22 ++++++++ .../com/zup/way/util/mapper/GastoMapper.java | 23 +++++++++ .../zup/way/util/swagger/SwaggerConfig.java | 50 +++++++++++++++++++ 5 files changed, 135 insertions(+) create mode 100644 src/main/java/br/com/zup/way/util/DateUtil.java create mode 100644 src/main/java/br/com/zup/way/util/Exception/WayBusinessException.java create mode 100644 src/main/java/br/com/zup/way/util/mapper/CategoriaMapper.java create mode 100644 src/main/java/br/com/zup/way/util/mapper/GastoMapper.java create mode 100644 src/main/java/br/com/zup/way/util/swagger/SwaggerConfig.java diff --git a/src/main/java/br/com/zup/way/util/DateUtil.java b/src/main/java/br/com/zup/way/util/DateUtil.java new file mode 100644 index 00000000..0a9034ac --- /dev/null +++ b/src/main/java/br/com/zup/way/util/DateUtil.java @@ -0,0 +1,29 @@ +package br.com.zup.way.util; + +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; + +public class DateUtil { + + private static final String PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"; + + public static LocalDateTime getStartDate(LocalDateTime dateToConvert) { + return setZone((dateToConvert.toLocalDate()).atStartOfDay()); + } + + public static LocalDateTime getEndDate(LocalDateTime dateToConvert) { + return setZone((dateToConvert.toLocalDate()).atTime(23, 59, 59)); + } + + public static LocalDateTime setZone(LocalDateTime localDateTime) { + return localDateTime + .atZone(ZoneId.of("UTC")) + .toLocalDateTime(); + } + + public static String format(LocalDateTime dateTime) { + return ZonedDateTime.of(dateTime, ZoneId.of("UTC")).format(DateTimeFormatter.ofPattern(PATTERN)); + } +} diff --git a/src/main/java/br/com/zup/way/util/Exception/WayBusinessException.java b/src/main/java/br/com/zup/way/util/Exception/WayBusinessException.java new file mode 100644 index 00000000..d0cb3897 --- /dev/null +++ b/src/main/java/br/com/zup/way/util/Exception/WayBusinessException.java @@ -0,0 +1,11 @@ +package br.com.zup.way.util.Exception; + +public class WayBusinessException extends Exception { + + private static final long serialVersionUID = 1L; + + public WayBusinessException(String msg) { + super(msg); + } + +} diff --git a/src/main/java/br/com/zup/way/util/mapper/CategoriaMapper.java b/src/main/java/br/com/zup/way/util/mapper/CategoriaMapper.java new file mode 100644 index 00000000..d0770baf --- /dev/null +++ b/src/main/java/br/com/zup/way/util/mapper/CategoriaMapper.java @@ -0,0 +1,22 @@ +package br.com.zup.way.util.mapper; + +import br.com.zup.way.db.solr.model.Categoria; +import br.com.zup.way.db.solr.model.dto.CategoriaDTO; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +@Mapper +public interface CategoriaMapper { + + CategoriaMapper INSTANCE = Mappers.getMapper(CategoriaMapper.class); + + CategoriaDTO categoriaToCategoriaDTO(Categoria categoria); + + List categoriaToCategoriaDTO(List categoria); + + @Mapping(target = "id", ignore = true) + Categoria categoriaDTOtoCategoria(CategoriaDTO categoria); +} diff --git a/src/main/java/br/com/zup/way/util/mapper/GastoMapper.java b/src/main/java/br/com/zup/way/util/mapper/GastoMapper.java new file mode 100644 index 00000000..3729ff6a --- /dev/null +++ b/src/main/java/br/com/zup/way/util/mapper/GastoMapper.java @@ -0,0 +1,23 @@ +package br.com.zup.way.util.mapper; + +import br.com.zup.way.db.solr.model.Gasto; +import br.com.zup.way.db.solr.model.dto.GastoDTO; +import br.com.zup.way.db.solr.model.dto.IntegrateGastoDTO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +@Mapper +public interface GastoMapper { + + GastoMapper INSTANCE = Mappers.getMapper(GastoMapper.class); + + GastoDTO gastoToGastoDTO(Gasto gasto); + + List gastoToGastoDTO(List gasto); + + Gasto gastoDTOtoGasto(GastoDTO gasto); + + Gasto gastoDTOtoGasto(IntegrateGastoDTO gastoDTO); +} diff --git a/src/main/java/br/com/zup/way/util/swagger/SwaggerConfig.java b/src/main/java/br/com/zup/way/util/swagger/SwaggerConfig.java new file mode 100644 index 00000000..6ce45e1f --- /dev/null +++ b/src/main/java/br/com/zup/way/util/swagger/SwaggerConfig.java @@ -0,0 +1,50 @@ +package br.com.zup.way.util.swagger; + +import br.com.zup.way.db.postgres.model.Usuario; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.ParameterBuilder; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.schema.ModelRef; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +import java.util.Arrays; + +@Configuration +@EnableSwagger2 +public class SwaggerConfig { + + @Bean + public Docket api() { + return new Docket(DocumentationType.SWAGGER_2) + .select() + .apis(RequestHandlerSelectors.basePackage("br.com.zup.way.controller")) + .build() + .apiInfo(apiInfo()) + .ignoredParameterTypes(Usuario.class) + .globalOperationParameters( + Arrays.asList(new ParameterBuilder() + .name("Authorization") + .description("Header for Token JWT") + .modelRef(new ModelRef("string")) + .parameterType("header") + .required(false).build() + ) + ); + } + + private ApiInfo apiInfo() { + return new ApiInfoBuilder() + .title("Gestão de Gastos") + .description("\"API REST para Gestão de Gastos\"") + .version("1.0.0") + .license("Apache License Version 2.0") + .licenseUrl("https://www.apache.org/licenses/LICENSE-2.0\"") + .build(); + } +} + From d56f43b58f539ca1ecbfaee8776563582cc9d299 Mon Sep 17 00:00:00 2001 From: "warley.rocha" Date: Mon, 1 Jul 2019 15:37:35 +0100 Subject: [PATCH 5/9] =?UTF-8?q?Implementa=C3=A7=C3=A3o=20de=20Seguran?= =?UTF-8?q?=C3=A7a=20com=20JWT?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controllers/AutenticationController.java | 35 ++++++++++ .../way/security/JWTAutenticationFilter.java | 52 +++++++++++++++ .../br/com/zup/way/security/JwtHelper.java | 10 +++ .../zup/way/security/WebSecurityConfig.java | 64 +++++++++++++++++++ .../com/zup/way/service/UsuarioService.java | 11 ++++ .../way/service/impl/UsuarioServiceImpl.java | 31 +++++++++ .../security/AutenticationService.java | 24 +++++++ .../way/service/security/JWTTokenService.java | 49 ++++++++++++++ 8 files changed, 276 insertions(+) create mode 100644 src/main/java/br/com/zup/way/controllers/AutenticationController.java create mode 100644 src/main/java/br/com/zup/way/security/JWTAutenticationFilter.java create mode 100644 src/main/java/br/com/zup/way/security/JwtHelper.java create mode 100644 src/main/java/br/com/zup/way/security/WebSecurityConfig.java create mode 100644 src/main/java/br/com/zup/way/service/UsuarioService.java create mode 100644 src/main/java/br/com/zup/way/service/impl/UsuarioServiceImpl.java create mode 100644 src/main/java/br/com/zup/way/service/security/AutenticationService.java create mode 100644 src/main/java/br/com/zup/way/service/security/JWTTokenService.java diff --git a/src/main/java/br/com/zup/way/controllers/AutenticationController.java b/src/main/java/br/com/zup/way/controllers/AutenticationController.java new file mode 100644 index 00000000..5f60cbce --- /dev/null +++ b/src/main/java/br/com/zup/way/controllers/AutenticationController.java @@ -0,0 +1,35 @@ +package br.com.zup.way.controllers; + +import br.com.zup.way.db.postgres.model.dto.LoginDTO; +import br.com.zup.way.db.postgres.model.dto.TokenDTO; +import br.com.zup.way.service.security.JWTTokenService; +import org.springframework.http.ResponseEntity; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.validation.Valid; + +@RestController +@RequestMapping("/auth") +public class AutenticationController { + + private AuthenticationManager authenticationManager; + private JWTTokenService tokenService; + + public AutenticationController(AuthenticationManager authenticationManager, JWTTokenService tokenService) { + this.authenticationManager = authenticationManager; + this.tokenService = tokenService; + } + + @PostMapping(path = "/") + public ResponseEntity authenticate(@RequestBody @Valid LoginDTO login) { + UsernamePasswordAuthenticationToken userNameToken = login.converter(); + Authentication authentication = authenticationManager.authenticate(userNameToken); + return ResponseEntity.ok(new TokenDTO(tokenService.generateToken(authentication), "Bearer")); + } +} diff --git a/src/main/java/br/com/zup/way/security/JWTAutenticationFilter.java b/src/main/java/br/com/zup/way/security/JWTAutenticationFilter.java new file mode 100644 index 00000000..3cc99047 --- /dev/null +++ b/src/main/java/br/com/zup/way/security/JWTAutenticationFilter.java @@ -0,0 +1,52 @@ +package br.com.zup.way.security; + +import br.com.zup.way.db.postgres.model.Usuario; +import br.com.zup.way.service.UsuarioService; +import br.com.zup.way.service.security.JWTTokenService; +import org.apache.commons.lang3.StringUtils; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.web.filter.OncePerRequestFilter; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +class JWTAutenticationFilter extends OncePerRequestFilter { + + private static final String HEADER_STRING = "Authorization"; + + private JWTTokenService tokenService; + + private UsuarioService usuarioService; + + public JWTAutenticationFilter(JWTTokenService tokenService, UsuarioService usuarioService) { + this.tokenService = tokenService; + this.usuarioService = usuarioService; + } + + @Override + protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException { + String token = getToken(httpServletRequest); + if (tokenService.isValidToken(token)) { + doAutentication(token); + } + filterChain.doFilter(httpServletRequest, httpServletResponse); + } + + private void doAutentication(String token) { + Usuario user = usuarioService.findById(tokenService.getIdByToken(token)); + SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities())); + } + + + private String getToken(HttpServletRequest httpServletRequest) { + String token = httpServletRequest.getHeader(HEADER_STRING); + if (StringUtils.isNotBlank(token) && token.startsWith("Bearer ")) { + return token.substring(7); + } + return null; + } +} diff --git a/src/main/java/br/com/zup/way/security/JwtHelper.java b/src/main/java/br/com/zup/way/security/JwtHelper.java new file mode 100644 index 00000000..9456be60 --- /dev/null +++ b/src/main/java/br/com/zup/way/security/JwtHelper.java @@ -0,0 +1,10 @@ +package br.com.zup.way.security; + +import br.com.zup.way.db.postgres.model.Usuario; +import org.springframework.security.core.context.SecurityContextHolder; + +public class JwtHelper { + public static Long getCodigoUsuario() { + return ((Usuario) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getId(); + } +} diff --git a/src/main/java/br/com/zup/way/security/WebSecurityConfig.java b/src/main/java/br/com/zup/way/security/WebSecurityConfig.java new file mode 100644 index 00000000..aad3262c --- /dev/null +++ b/src/main/java/br/com/zup/way/security/WebSecurityConfig.java @@ -0,0 +1,64 @@ +package br.com.zup.way.security; + +import br.com.zup.way.service.UsuarioService; +import br.com.zup.way.service.security.AutenticationService; +import br.com.zup.way.service.security.JWTTokenService; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpMethod; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.builders.WebSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; + +@EnableWebSecurity +@Configuration +public class WebSecurityConfig extends WebSecurityConfigurerAdapter { + + private AutenticationService authenticationService; + + private JWTTokenService tokenService; + + private UsuarioService usuarioService; + + public WebSecurityConfig(AutenticationService authenticationService, JWTTokenService tokenService, UsuarioService usuarioService) { + this.authenticationService = authenticationService; + this.tokenService = tokenService; + this.usuarioService = usuarioService; + } + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth.userDetailsService(authenticationService).passwordEncoder(new BCryptPasswordEncoder()); + } + + @Override + @Bean + protected AuthenticationManager authenticationManager() throws Exception { + return super.authenticationManager(); + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.authorizeRequests() + .antMatchers(HttpMethod.POST, "/auth/*").permitAll() + .antMatchers("/admin/api/*").hasRole("ADMIN") + .antMatchers("/user/api/*").hasRole("USER") + .antMatchers("/sys/api/*").hasRole("SYS") + .anyRequest().authenticated() + .and().csrf().disable() + .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) + .and().addFilterBefore(new JWTAutenticationFilter(tokenService, usuarioService), UsernamePasswordAuthenticationFilter.class); + } + + @Override + public void configure(WebSecurity web) { + web.ignoring().antMatchers("/v2/api-docs", "/configuration/ui", "/swagger-resources/**", "/configuration/**", "/swagger-ui.html", "/webjars/**"); + } + +} diff --git a/src/main/java/br/com/zup/way/service/UsuarioService.java b/src/main/java/br/com/zup/way/service/UsuarioService.java new file mode 100644 index 00000000..f01d3b90 --- /dev/null +++ b/src/main/java/br/com/zup/way/service/UsuarioService.java @@ -0,0 +1,11 @@ +package br.com.zup.way.service; + +import br.com.zup.way.db.postgres.model.Usuario; +import br.com.zup.way.util.Exception.WayBusinessException; + +public interface UsuarioService { + + Usuario findById(Long idUsuario); + + Usuario findClienteByCodigoUsuario(Long codigoUsuario) throws WayBusinessException; +} diff --git a/src/main/java/br/com/zup/way/service/impl/UsuarioServiceImpl.java b/src/main/java/br/com/zup/way/service/impl/UsuarioServiceImpl.java new file mode 100644 index 00000000..3830cdf1 --- /dev/null +++ b/src/main/java/br/com/zup/way/service/impl/UsuarioServiceImpl.java @@ -0,0 +1,31 @@ +package br.com.zup.way.service.impl; + +import br.com.zup.way.db.postgres.model.Usuario; +import br.com.zup.way.db.postgres.repository.UsuarioRepository; +import br.com.zup.way.service.UsuarioService; +import br.com.zup.way.util.Exception.WayBusinessException; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; + +@Service +public class UsuarioServiceImpl implements UsuarioService { + + private static final Integer CLIENTE = 1; + + private UsuarioRepository usuarioRepository; + + public UsuarioServiceImpl(UsuarioRepository usuarioRepository) { + this.usuarioRepository = usuarioRepository; + } + + public Usuario findById(Long idUsuario) { + return usuarioRepository.findById(idUsuario) + .orElseThrow(() -> new UsernameNotFoundException("Usuario não Encontrado")); + } + + @Override + public Usuario findClienteByCodigoUsuario(Long codigoUsuario) throws WayBusinessException { + return usuarioRepository.findByIdAndTipo(codigoUsuario, CLIENTE) + .orElseThrow(() -> new WayBusinessException("Usuario não Encontrado")); + } +} diff --git a/src/main/java/br/com/zup/way/service/security/AutenticationService.java b/src/main/java/br/com/zup/way/service/security/AutenticationService.java new file mode 100644 index 00000000..5dc8e382 --- /dev/null +++ b/src/main/java/br/com/zup/way/service/security/AutenticationService.java @@ -0,0 +1,24 @@ +package br.com.zup.way.service.security; + +import br.com.zup.way.db.postgres.repository.UsuarioRepository; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; + +@Service +public class AutenticationService implements UserDetailsService { + + private UsuarioRepository usuarioRepository; + + public AutenticationService(UsuarioRepository usuarioRepository) { + this.usuarioRepository = usuarioRepository; + } + + @Override + public UserDetails loadUserByUsername(String login) throws UsernameNotFoundException { + return usuarioRepository.findByLogin(login) + .orElseThrow(() -> new UsernameNotFoundException("Username: " + login + " não encontrado")); + } + +} diff --git a/src/main/java/br/com/zup/way/service/security/JWTTokenService.java b/src/main/java/br/com/zup/way/service/security/JWTTokenService.java new file mode 100644 index 00000000..3f373c40 --- /dev/null +++ b/src/main/java/br/com/zup/way/service/security/JWTTokenService.java @@ -0,0 +1,49 @@ +package br.com.zup.way.service.security; + +import br.com.zup.way.db.postgres.model.Usuario; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import io.jsonwebtoken.SignatureException; +import org.apache.commons.lang3.time.DateUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Service; + +import java.util.Date; + +@Service +public class JWTTokenService { + + @Value("${way.jwt.expiration}") + private String expiration; + + @Value("${way.jwt.secret}") + private String secret; + + + public String generateToken(Authentication authentication) { + return Jwts.builder() + .setIssuer("API Way") + .setSubject(((Usuario) authentication.getPrincipal()).getId().toString()) + .setIssuedAt(new Date()) + .setExpiration(DateUtils.addMilliseconds(new Date(), Integer.valueOf(expiration))) + .signWith(SignatureAlgorithm.HS256, secret) + .compact(); + } + + public boolean isValidToken(String token) { + try { + if (token != null) { + Jwts.parser().setSigningKey(secret).parseClaimsJws(token); + return true; + } + } catch (SignatureException sign) { + return false; + } + return false; + } + + public Long getIdByToken(String token) { + return Long.parseLong(Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody().getSubject()); + } +} From ec373f12d21b5cb4b22b93ae24033f61cedaf5c7 Mon Sep 17 00:00:00 2001 From: "warley.rocha" Date: Mon, 1 Jul 2019 15:38:12 +0100 Subject: [PATCH 6/9] =?UTF-8?q?Implementa=C3=A7=C3=A3o=20das=20regras=20do?= =?UTF-8?q?=20Rest=20de=20Gasto?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../zup/way/controllers/GastoController.java | 51 +++++++++ .../br/com/zup/way/service/GastoService.java | 24 ++++ .../way/service/impl/GastoServiceImpl.java | 104 ++++++++++++++++++ .../zup/way/gasto/GastoApplicationTests.java | 50 +++++++++ .../zup/way/gasto/GastoIntegrationTests.java | 97 ++++++++++++++++ 5 files changed, 326 insertions(+) create mode 100644 src/main/java/br/com/zup/way/controllers/GastoController.java create mode 100644 src/main/java/br/com/zup/way/service/GastoService.java create mode 100644 src/main/java/br/com/zup/way/service/impl/GastoServiceImpl.java create mode 100644 src/test/java/br/com/zup/way/gasto/GastoApplicationTests.java create mode 100644 src/test/java/br/com/zup/way/gasto/GastoIntegrationTests.java diff --git a/src/main/java/br/com/zup/way/controllers/GastoController.java b/src/main/java/br/com/zup/way/controllers/GastoController.java new file mode 100644 index 00000000..18f43a52 --- /dev/null +++ b/src/main/java/br/com/zup/way/controllers/GastoController.java @@ -0,0 +1,51 @@ +package br.com.zup.way.controllers; + +import br.com.zup.way.db.solr.model.dto.FiltroCategorizarGastoDTO; +import br.com.zup.way.db.solr.model.dto.FiltroGastoDTO; +import br.com.zup.way.db.solr.model.dto.GastoDTO; +import br.com.zup.way.db.solr.model.dto.IntegrateGastoDTO; +import br.com.zup.way.security.JwtHelper; +import br.com.zup.way.service.GastoService; +import br.com.zup.way.util.Exception.WayBusinessException; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.List; +import java.util.Set; + +@RestController +@RequestMapping +public class GastoController { + + private GastoService gastoService; + + public GastoController(GastoService gastoService) { + this.gastoService = gastoService; + } + + @PutMapping(path = "/sys/api/gasto/integracao") + public GastoDTO integrate(@RequestBody @Valid IntegrateGastoDTO gastoDTO) throws WayBusinessException { + return gastoService.integrateGasto(gastoDTO); + } + + @PutMapping(path = "/user/api/gasto/categorizar") + public GastoDTO categorizarGasto(@RequestBody @Valid FiltroCategorizarGastoDTO filtro) throws WayBusinessException { + return gastoService.categorizarGasto(filtro); + } + + @GetMapping(path = "/user/api/gasto/last") + public List listLast() { + return gastoService.findLastGastos(JwtHelper.getCodigoUsuario()); + } + + @PostMapping(path = "/user/api/gasto/find") + public List find(@RequestBody @Valid FiltroGastoDTO filtroData) { + return gastoService.findGastosByDate(JwtHelper.getCodigoUsuario(), filtroData); + } + + @GetMapping(path = "/user/api/gasto/categoria/{nomeCategoria}") + public Set suggestCategoria(@PathVariable("nomeCategoria") String nomeCategoria) { + return gastoService.findCategoria(nomeCategoria); + } + +} diff --git a/src/main/java/br/com/zup/way/service/GastoService.java b/src/main/java/br/com/zup/way/service/GastoService.java new file mode 100644 index 00000000..a3a360c0 --- /dev/null +++ b/src/main/java/br/com/zup/way/service/GastoService.java @@ -0,0 +1,24 @@ +package br.com.zup.way.service; + +import br.com.zup.way.db.solr.model.dto.FiltroCategorizarGastoDTO; +import br.com.zup.way.db.solr.model.dto.FiltroGastoDTO; +import br.com.zup.way.db.solr.model.dto.GastoDTO; +import br.com.zup.way.db.solr.model.dto.IntegrateGastoDTO; +import br.com.zup.way.util.Exception.WayBusinessException; + +import java.util.List; +import java.util.Set; + +public interface GastoService { + + GastoDTO categorizarGasto(FiltroCategorizarGastoDTO filtro) throws WayBusinessException; + + GastoDTO integrateGasto(IntegrateGastoDTO gastoDTO) throws WayBusinessException; + + List findLastGastos(Long codigoUsuario); + + List findGastosByDate(Long codigoUsuario, FiltroGastoDTO filtroData); + + Set findCategoria(String nomeCategoria); + +} diff --git a/src/main/java/br/com/zup/way/service/impl/GastoServiceImpl.java b/src/main/java/br/com/zup/way/service/impl/GastoServiceImpl.java new file mode 100644 index 00000000..6565bac2 --- /dev/null +++ b/src/main/java/br/com/zup/way/service/impl/GastoServiceImpl.java @@ -0,0 +1,104 @@ +package br.com.zup.way.service.impl; + +import br.com.zup.way.db.solr.model.Gasto; +import br.com.zup.way.db.solr.model.dto.FiltroCategorizarGastoDTO; +import br.com.zup.way.db.solr.model.dto.FiltroGastoDTO; +import br.com.zup.way.db.solr.model.dto.GastoDTO; +import br.com.zup.way.db.solr.model.dto.IntegrateGastoDTO; +import br.com.zup.way.db.solr.repository.GastoRepository; +import br.com.zup.way.security.JwtHelper; +import br.com.zup.way.service.GastoService; +import br.com.zup.way.service.UsuarioService; +import br.com.zup.way.util.DateUtil; +import br.com.zup.way.util.Exception.WayBusinessException; +import org.apache.commons.lang3.StringUtils; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +@Service +public class GastoServiceImpl implements GastoService { + + private GastoRepository gastoRepository; + + private UsuarioService usuarioService; + + public GastoServiceImpl(GastoRepository gastoRepository, UsuarioService usuarioService) { + this.gastoRepository = gastoRepository; + this.usuarioService = usuarioService; + } + + @Override + public GastoDTO integrateGasto(IntegrateGastoDTO gastoDTO) throws WayBusinessException { + validateCodigoUsuario(gastoDTO.getCodigoUsuario()); + Gasto gasto = Gasto.convert(gastoDTO); + if (gasto.getDataCadastro() == null) { + gasto.setDataCadastro(DateUtil.setZone(LocalDateTime.now())); + } + gasto.setCategoria(findCategoriaByGasto(gastoDTO)); + return GastoDTO.convert(gastoRepository.save(gasto)); + } + + @Override + public GastoDTO categorizarGasto(FiltroCategorizarGastoDTO filtro) throws WayBusinessException { + Gasto gasto = findById(filtro.getIdGasto()); + if (StringUtils.isNotBlank(gasto.getCategoria())) { + throw new WayBusinessException("Esse gasto já foi categorizado"); + } + gasto.setCategoria(filtro.getCategoria()); + return GastoDTO.convert(gastoRepository.save(gasto)); + } + + @Override + public List findLastGastos(Long codigoUsuario) { + return GastoDTO.convert( + gastoRepository.findGastoByCodigoUsuarioAndDataCadastroLessThanEqual( + codigoUsuario, DateUtil.format(LocalDateTime.now().minusSeconds(5)), + PageRequest.of(0, 15, + Sort.by(Sort.Order.desc("dataCadastro"), Sort.Order.asc("descricao"))) + ) + ); + } + + @Override + public List findGastosByDate(Long codigoUsuario, FiltroGastoDTO filtroData) { + return GastoDTO.convert( + gastoRepository.findGastoByCodigoUsuarioAndDataCadastroBetween( + codigoUsuario, + DateUtil.format(DateUtil.getStartDate(filtroData.getFiltroData())), + DateUtil.format(DateUtil.getEndDate(filtroData.getFiltroData())), + Sort.by(Sort.Order.desc("dataCadastro")) + ) + ); + } + + @Override + public Set findCategoria(String nomeCategoria) { + List gastos = + gastoRepository.findGastoByCategoriaContainingIgnoreCaseAndCodigoUsuarioOrderByCategoria(nomeCategoria, JwtHelper.getCodigoUsuario()); + return gastos.stream().map(Gasto::getCategoria).collect(Collectors.toSet()); + } + + /** + * Private Methods + */ + + private void validateCodigoUsuario(Long codigoUsuario) throws WayBusinessException { + usuarioService.findClienteByCodigoUsuario(codigoUsuario); + } + + private String findCategoriaByGasto(IntegrateGastoDTO gastoDTO) { + List gastos = + gastoRepository.findGastoByDescricaoIgnoreCaseAndCodigoUsuario(gastoDTO.getDescricao(), gastoDTO.getCodigoUsuario()); + return gastos.stream().findFirst().orElse(new Gasto()).getCategoria(); + } + + private Gasto findById(String idGasto) throws WayBusinessException { + return gastoRepository.findById(idGasto).orElseThrow(() -> new WayBusinessException("Gasto não Encontrado.")); + } +} diff --git a/src/test/java/br/com/zup/way/gasto/GastoApplicationTests.java b/src/test/java/br/com/zup/way/gasto/GastoApplicationTests.java new file mode 100644 index 00000000..f9bf5b04 --- /dev/null +++ b/src/test/java/br/com/zup/way/gasto/GastoApplicationTests.java @@ -0,0 +1,50 @@ +package br.com.zup.way.gasto; + +import br.com.zup.way.db.solr.model.Gasto; +import br.com.zup.way.db.solr.model.dto.FiltroCategorizarGastoDTO; +import br.com.zup.way.db.solr.repository.GastoRepository; +import br.com.zup.way.service.impl.GastoServiceImpl; +import br.com.zup.way.util.DateUtil; +import br.com.zup.way.util.Exception.WayBusinessException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +import java.time.LocalDateTime; +import java.util.Optional; + +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class GastoApplicationTests { + + @Mock + GastoRepository gastoRepositoryMock; + + @InjectMocks + GastoServiceImpl gastoService; + + @Test(expected = WayBusinessException.class) + public void categorizarGasto() throws WayBusinessException { + LocalDateTime data = DateUtil.setZone(LocalDateTime.now()); + when(gastoRepositoryMock.findById("7bd92702-ddc2-4286-a2ec-1e362c5d77b3")) + .thenReturn(returnGasto("7bd92702-ddc2-4286-a2ec-1e362c5d77b3", "Supermercado Extra", 200D, 2L, "SuperMercado", data)); + gastoService.categorizarGasto(returnFiltroCategorizarGastoDTO("Supermercado Extra", "7bd92702-ddc2-4286-a2ec-1e362c5d77b3")); + } + + private FiltroCategorizarGastoDTO returnFiltroCategorizarGastoDTO(String categoria, String idGasto) { + return new FiltroCategorizarGastoDTO(categoria, idGasto); + } + + /** + * Private Methods + * + * @return + */ + private Optional returnGasto(String id, String descricao, Double valor, Long codigoUsuario, String categoria, LocalDateTime dataCadastro) { + return Optional.of(new Gasto(id, descricao, valor, codigoUsuario, categoria, dataCadastro)); + } + +} \ No newline at end of file diff --git a/src/test/java/br/com/zup/way/gasto/GastoIntegrationTests.java b/src/test/java/br/com/zup/way/gasto/GastoIntegrationTests.java new file mode 100644 index 00000000..fc9f795f --- /dev/null +++ b/src/test/java/br/com/zup/way/gasto/GastoIntegrationTests.java @@ -0,0 +1,97 @@ +package br.com.zup.way.gasto; + +import br.com.zup.way.controllers.GastoController; +import br.com.zup.way.db.solr.model.dto.FiltroCategorizarGastoDTO; +import br.com.zup.way.db.solr.model.dto.FiltroGastoDTO; +import br.com.zup.way.db.solr.model.dto.GastoDTO; +import br.com.zup.way.db.solr.model.dto.IntegrateGastoDTO; +import br.com.zup.way.util.DateUtil; +import br.com.zup.way.util.Exception.WayBusinessException; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Profile; +import org.springframework.security.test.context.support.WithUserDetails; +import org.springframework.test.context.junit4.SpringRunner; + +import java.time.LocalDateTime; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +@RunWith(SpringRunner.class) +@SpringBootTest +@WithUserDetails +@Profile("test") +public class GastoIntegrationTests { + + @Autowired + GastoController gastoController; + private LocalDateTime dataCadastro = DateUtil.setZone(LocalDateTime.of(2019, 01, 01, 8, 00)); + + @Test + public void testIntegrateGastoWithouCategoria() throws WayBusinessException { + GastoDTO gasto = gastoController.integrate(new IntegrateGastoDTO(2L, "SuperMercado Santana", 200.20D, dataCadastro)); + Assert.assertEquals(createGasto("SuperMercado Santana", 200.20D, null), gasto); + } + + @Test + public void testIntegrateGastoWithCategoria() throws WayBusinessException { + GastoDTO gasto = gastoController.integrate(new IntegrateGastoDTO(2L, "TAM SITE", 400D, dataCadastro)); + Assert.assertEquals(createGasto("TAM SITE", 400D, "Viagem"), gasto); + } + + @Test(expected = WayBusinessException.class) + public void testIntegrateGastoWithoutValidUser() throws WayBusinessException { + gastoController.integrate(new IntegrateGastoDTO(3L, "Inclusão Cliente Invalido", 200.20D, dataCadastro)); + } + + @Test + public void testCategorizarGasto() throws WayBusinessException { + GastoDTO gasto = gastoController.categorizarGasto(new FiltroCategorizarGastoDTO("Viagem", "513b08d9-b286-4da4-a09f-33d15687e972")); + Assert.assertEquals(createGasto("TAM SITE", 300D, "Viagem"), gasto); + } + + @Test + public void testSuggestCategoria() { + Set categorias = gastoController.suggestCategoria("agem"); + Assert.assertEquals(new HashSet<>(Arrays.asList("Viagem")), categorias); + } + + @Test + public void testFind() { + List gasto = gastoController.find(new FiltroGastoDTO(dataCadastro)); + Assert.assertEquals( + Arrays.asList( + createGasto("TAM SITE", 300D, null), + createGasto("Padaria No Céu", 50D, "Restaurante"), + createGasto("Uber Do Brasil", 10D, "Transporte") + ), gasto); + + } + + @Test + public void testlistLast() { + List gasto = gastoController.listLast(); + Assert.assertEquals( + Arrays.asList( + createGasto("Uber Do Brasil", 10D, "Transporte"), + createGasto("Padaria No Céu", 50D, "Restaurante"), + createGasto("SuperMercado Santana", 200.2D, null), + createGasto("TAM SITE", 300D, "Viagem"), + createGasto("TAM SITE", 400D, "Viagem") + ), gasto); + } + + + /** + * Private Methods + */ + + private GastoDTO createGasto(String descricao, double valor, String categoria) { + return new GastoDTO(null, descricao, valor, 2L, dataCadastro, categoria); + } +} From 4782c0b15e71d7b216b6a5b58cad1536a12824bf Mon Sep 17 00:00:00 2001 From: "warley.rocha" Date: Mon, 1 Jul 2019 15:48:41 +0100 Subject: [PATCH 7/9] =?UTF-8?q?Altera=C3=A7=C3=A3o=20no=20Pom?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 63 ++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 25 deletions(-) diff --git a/pom.xml b/pom.xml index 4e660af2..7c7768f6 100644 --- a/pom.xml +++ b/pom.xml @@ -52,14 +52,14 @@ - org.springframework.boot - spring-boot-starter-web + io.dropwizard.metrics + metrics-core + 3.2.6 org.springframework.boot - spring-boot-starter-test - test + spring-boot-starter-web @@ -69,6 +69,24 @@ true + + org.projectlombok + lombok + true + + + + org.mapstruct + mapstruct + ${org.mapstruct.version} + + + + org.springframework.boot + spring-boot-starter-test + test + + org.springframework.security spring-security-test @@ -76,9 +94,9 @@ - org.springframework.security - spring-security-jwt - ${jwt.version} + io.springfox + springfox-swagger2 + 2.9.2 @@ -101,28 +119,17 @@ spring-data-solr + - org.projectlombok - lombok - true - - - - io.dropwizard.metrics - metrics-core - 3.2.6 - - - - org.mapstruct - mapstruct - ${org.mapstruct.version} + org.springframework.security.oauth + spring-security-oauth2 + ${oauth.version} - io.springfox - springfox-swagger2 - 2.9.2 + org.springframework.security + spring-security-jwt + ${jwt.version} @@ -167,6 +174,12 @@ 5.2.4 + + com.h2database + h2 + runtime + + io.jsonwebtoken jjwt From 6d5e19b417ed8fed04730626c1073aca43a4bc6d Mon Sep 17 00:00:00 2001 From: "warley.rocha" Date: Mon, 1 Jul 2019 16:05:36 +0100 Subject: [PATCH 8/9] =?UTF-8?q?Documenta=C3=A7=C3=A3o=20do=20Readme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 108 ++++++++++++++++++++++++++---------------------------- 1 file changed, 52 insertions(+), 56 deletions(-) diff --git a/README.md b/README.md index 15d8f685..a5dabcc2 100644 --- a/README.md +++ b/README.md @@ -1,76 +1,72 @@ -# Show me the code +# Santander Way +Gerenciamento de Gastos Way -### # DESAFIO: +Aplicação feita com Spring Boot, Spring Data com Banco Postgress (Permissão) e Solr(Gasto), Rest com swagger. -API REST para Gestão de Gastos! +

Subindo Aplicação Completa

+ +Para rodar a aplicação deve-se criar um banco Postgress(Usuario:posrgres Senha:admin) + +Criar um database com nome way + +Deve-se também criar um banco Solr + +Entrar na pasta bin do Solr e rodar o comando ``` -Funcionalidade: Integração de gastos por cartão - Apenas sistemas credenciados poderão incluir novos gastos - É esperado um volume de 100.000 inclusões por segundo - Os gastos, serão informados atraves do protoloco JSON, seguindo padrão: - { "descricao": "alfanumerico", "valor": double americano, "codigousuario": numerico, "data": Data dem formato UTC } -``` -``` -Funcionalidade: Listagem de gastos* - Dado que acesso como um cliente autenticado que pode visualizar os gastos do cartão - Quando acesso a interface de listagem de gastos - Então gostaria de ver meus gastos mais atuais. - -*Para esta funcionalidade é esperado 2.000 acessos por segundo. -*O cliente espera ver gastos realizados a 5 segundos atrás. +.\solr start ``` + +Para que o mesmo seja iniciado e então rodar o comando + ``` -Funcionalidade: Filtro de gastos - Dado que acesso como um cliente autenticado - E acessei a interface de listagem de gastos - E configure o filtro de data igual a 27/03/1992 - Então gostaria de ver meus gastos apenas deste dia. +.\solr create -c GastoSolr ``` +Assim será adicionado um core chamado GastoSolr + +Logo após entrar na pasta do projeto rodar o comando + ``` -Funcionalidade: Categorização de gastos - Dado que acesso como um cliente autenticado - Quando acesso o detalhe de um gasto - E este não possui uma categoria - Então devo conseguir incluir uma categoria para este +mvn spring-boot:run ``` + +O flyWay irá criar as tabelas necessárias + +Criará também 3 usuarios + +Admin (Senha : admin - Id = 1) - usuario admin + +User (Senha : user - Id = 2 ) - Usuário do tipo cliente que pode receber inclusão de gastos + +Sys (Senha : sys - Id = 3) - Usuário do tipo sistema que pode incluir gastos + +aplicação estará com os endpoints disponíveis em : + ``` -Funcionalidade: Sugestão de categoria - Dado que acesso como um cliente autenticado - Quando acesso o detalhe do gasto que não possui categoria - E começo a digitar a categoria que desejo - Então uma lista de sugestões de categoria deve ser exibida, estas baseadas em categorias já informadas por outro usuários. +http://localhost:8080/swagger-ui.html ``` + +

Testes com Mokito

+ +Para rodar a classe de testes configurada com as conexão de banco mokadas (Mokito) + +Deve-se executar o seguinte comando: + ``` -Funcionalidade: Categorização automatica de gasto - No processo de integração de gastos, a categoria deve ser incluida automaticamente - caso a descrição de um gasto seja igual a descrição de qualquer outro gasto já categorizado pelo cliente - o mesmo deve receber esta categoria no momento da inclusão do mesmo +mvn clean test -Dtest=br.com.zup.way.gasto.GastoApplicationTests ``` -### # Avaliação -Você será avaliado pela usabilidade, por respeitar o design e pela arquitetura da API. -É esperado que você consiga explicar as decisões que tomou durante o desenvolvimento através de commits. +Com isso os testes dos serviços irão rodar sem necessidade de conexão com o banco. -* Springboot - Java - Maven (preferêncialmente) ([https://projects.spring.io/spring-boot/](https://projects.spring.io/spring-boot/)) -* RESTFul ([https://blog.mwaysolutions.com/2014/06/05/10-best-practices-for-better-restful-api/](https://blog.mwaysolutions.com/2014/06/05/10-best-practices-for-better-restful-api/)) -* DDD ([https://airbrake.io/blog/software-design/domain-driven-design](https://airbrake.io/blog/software-design/domain-driven-design)) -* Microservices ([https://martinfowler.com/microservices/](https://martinfowler.com/microservices/)) -* Testes unitários, teste o que achar importante (De preferência JUnit + Mockito). Mas pode usar o que você tem mais experiência, só nos explique o que ele tem de bom. -* SOAPUI para testes de carga ([https://www.soapui.org/load-testing/concept.html](https://www.soapui.org/load-testing/concept.html)) -* Uso de diferentes formas de armazenamento de dados (REDIS, Cassandra, Solr/Lucene) -* Uso do git -* Diferencial: Criptografia de comunicação, com troca de chaves. ([http://noiseprotocol.org/](http://noiseprotocol.org/)) -* Diferencial: CQRS ([https://martinfowler.com/bliki/CQRS.html](https://martinfowler.com/bliki/CQRS.html)) -* Diferencial: Docker File + Docker Compose (com dbs) para rodar seus jars. +

Testes de Integração

-### # Observações gerais +Deve-se executar o seguinte comando: -Adicione um arquivo [README.md](http://README.md) com os procedimentos para executar o projeto. -Pedimos que trabalhe sozinho e não divulgue o resultado na internet. +``` +mvn clean test -Dtest=br.com.zup.way.gasto.GastoIntegrationTests +``` -Faça um fork desse desse repositório em seu Github e nos envie um Pull Request com o resultado, por favor informe por qual empresa você esta se candidatando. +Irá ser criado um banco do Solr em mémoria e configurado alguns registros bases para o teste. -### # Importante: não há prazo de entrega, faça com qualidade! +O banco postgres já deve ter sido criado para que o mesmo possa validar as informações de usuário. -# BOA SORTE! From 359f956c6e3de29eca6b50b36d06ce793853a427 Mon Sep 17 00:00:00 2001 From: "warley.rocha" Date: Mon, 1 Jul 2019 16:23:27 +0100 Subject: [PATCH 9/9] =?UTF-8?q?Documenta=C3=A7=C3=A3o=20do=20Readme=20e=20?= =?UTF-8?q?configura=C3=A7=C3=A3o=20do=20Solr?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 26 +- src/main/resources/Solr/managed-schema.xml | 1018 ++++++++++++++++++++ 2 files changed, 1039 insertions(+), 5 deletions(-) create mode 100644 src/main/resources/Solr/managed-schema.xml diff --git a/README.md b/README.md index a5dabcc2..cf5c3bd5 100644 --- a/README.md +++ b/README.md @@ -5,11 +5,11 @@ Aplicação feita com Spring Boot, Spring Data com Banco Postgress (Permissão)

Subindo Aplicação Completa

-Para rodar a aplicação deve-se criar um banco Postgress(Usuario:posrgres Senha:admin) +Para rodar a aplicação deve-se criar um banco Postgress(Usuario:psotgres Senha:admin) Criar um database com nome way -Deve-se também criar um banco Solr +Deve-se também criar um banco Solr (8.1.1) Entrar na pasta bin do Solr e rodar o comando @@ -17,13 +17,30 @@ Entrar na pasta bin do Solr e rodar o comando .\solr start ``` -Para que o mesmo seja iniciado e então rodar o comando +Para que o mesmo seja iniciado. Então rodar o comando : ``` .\solr create -c GastoSolr ``` + Assim será adicionado um core chamado GastoSolr +Então deve-se copiar o arquivo ./resources/Solr/managed-schema.xml e substituir o mesmo na pasta + +%SOLAR_INSTALATION_DIR%\server\solr\GastoSolr\conf + +pode ser necessário restartar o Solr + +``` +.\solr stop -p 8983 +``` + +Depois + +``` +.\solr start +``` + Logo após entrar na pasta do projeto rodar o comando ``` @@ -68,5 +85,4 @@ mvn clean test -Dtest=br.com.zup.way.gasto.GastoIntegrationTests Irá ser criado um banco do Solr em mémoria e configurado alguns registros bases para o teste. -O banco postgres já deve ter sido criado para que o mesmo possa validar as informações de usuário. - +O banco postgres já deve ter sido criado para que o mesmo possa validar as informações de usuário. \ No newline at end of file diff --git a/src/main/resources/Solr/managed-schema.xml b/src/main/resources/Solr/managed-schema.xml new file mode 100644 index 00000000..7f68b504 --- /dev/null +++ b/src/main/resources/Solr/managed-schema.xml @@ -0,0 +1,1018 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + id + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +