From 370566f02b263580d6ffd98fdf05a7a29609f65a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Vitor?= Date: Thu, 12 Sep 2024 17:23:24 -0300 Subject: [PATCH 01/18] refactory: clean repository files --- .../springboot/repository/CompetenciaRepository.java | 2 +- .../springboot/repository/ConteudoRepository.java | 3 +-- .../repository/ListaQuestoesRepository.java | 8 +------- .../springboot/repository/QuestaoRepository.java | 12 ------------ .../repository/UsuarioPermissaoRepository.java | 1 - .../springboot/repository/UsuarioRepository.java | 8 -------- 6 files changed, 3 insertions(+), 31 deletions(-) diff --git a/backend/src/main/java/springboot/repository/CompetenciaRepository.java b/backend/src/main/java/springboot/repository/CompetenciaRepository.java index 74e711f7..12700f86 100644 --- a/backend/src/main/java/springboot/repository/CompetenciaRepository.java +++ b/backend/src/main/java/springboot/repository/CompetenciaRepository.java @@ -2,10 +2,10 @@ import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.stereotype.Repository; + import springboot.model.Competencia; @Repository public interface CompetenciaRepository extends MongoRepository { - } \ No newline at end of file diff --git a/backend/src/main/java/springboot/repository/ConteudoRepository.java b/backend/src/main/java/springboot/repository/ConteudoRepository.java index 71993316..595d1a37 100644 --- a/backend/src/main/java/springboot/repository/ConteudoRepository.java +++ b/backend/src/main/java/springboot/repository/ConteudoRepository.java @@ -2,11 +2,10 @@ import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.stereotype.Repository; + import springboot.model.Conteudo; -import springboot.model.Usuario; @Repository public interface ConteudoRepository extends MongoRepository { - } \ No newline at end of file diff --git a/backend/src/main/java/springboot/repository/ListaQuestoesRepository.java b/backend/src/main/java/springboot/repository/ListaQuestoesRepository.java index 37ed13f0..9591b056 100644 --- a/backend/src/main/java/springboot/repository/ListaQuestoesRepository.java +++ b/backend/src/main/java/springboot/repository/ListaQuestoesRepository.java @@ -1,20 +1,14 @@ package springboot.repository; -import java.util.Optional; - import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.mongodb.repository.MongoRepository; -import org.springframework.data.mongodb.repository.Query; -import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; import springboot.model.ListaQuestoes; -import springboot.model.Usuario; - @Repository -public interface ListaQuestoesRepository extends MongoRepository{ +public interface ListaQuestoesRepository extends MongoRepository { Page getByAutor(String autor, Pageable pageable); diff --git a/backend/src/main/java/springboot/repository/QuestaoRepository.java b/backend/src/main/java/springboot/repository/QuestaoRepository.java index 6072b911..de4eb5f7 100644 --- a/backend/src/main/java/springboot/repository/QuestaoRepository.java +++ b/backend/src/main/java/springboot/repository/QuestaoRepository.java @@ -1,11 +1,9 @@ package springboot.repository; import java.util.List; -import java.util.Optional; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.data.mongodb.repository.Query; import org.springframework.data.repository.query.Param; @@ -13,23 +11,13 @@ import springboot.enums.EstadoQuestao; import springboot.model.Questao; -import springboot.model.Usuario; @Repository public abstract interface QuestaoRepository extends MongoRepository { - Page findAllByEstado(EstadoQuestao estado, Pageable pageable); - Optional findById(String id); - - @Query(":#{#query}") Page getByEnunciadoCompetenciasAutorFonteTipo(@Param("query") String query, Pageable pageable); List getByEstadoAndQtdAvaliacoesGreaterThan(EstadoQuestao estado, int qtd); - - //@Query("SELECT q FROM Question q WHERE q.qtdAvaliacoes <= 3 AND NOT EXISTS (SELECT a FROM Avaliacao a WHERE a.questao = q AND a.autor = ?1)") - //@org.springframework.data.jpa.repository.Query(value = "SELECT q FROM questao q", nativeQuery = false) - //Page getPendentes(Usuario usuario, Pageable pageable); - } diff --git a/backend/src/main/java/springboot/repository/UsuarioPermissaoRepository.java b/backend/src/main/java/springboot/repository/UsuarioPermissaoRepository.java index a21dc4e0..df4ee12e 100644 --- a/backend/src/main/java/springboot/repository/UsuarioPermissaoRepository.java +++ b/backend/src/main/java/springboot/repository/UsuarioPermissaoRepository.java @@ -1,6 +1,5 @@ package springboot.repository; - import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.stereotype.Repository; diff --git a/backend/src/main/java/springboot/repository/UsuarioRepository.java b/backend/src/main/java/springboot/repository/UsuarioRepository.java index 4f21bce8..14e3d4c4 100644 --- a/backend/src/main/java/springboot/repository/UsuarioRepository.java +++ b/backend/src/main/java/springboot/repository/UsuarioRepository.java @@ -1,6 +1,5 @@ package springboot.repository; - import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; @@ -11,11 +10,4 @@ @Transactional public interface UsuarioRepository extends MongoRepository { - /* - * @Query("SELECT d FROM Disciplina d WHERE LOWER(d.nome) LIKE CONCAT('%', LOWER(:nome), '%')" - * ) public List pesquisarPorNome(@Param("nome") String nome); - */ - - //Usuario findByEmail(String email); - } From b133765f94b9f8581a758afcaa306a6db8713a51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Vitor?= Date: Thu, 12 Sep 2024 17:42:29 -0300 Subject: [PATCH 02/18] refactory: clean AepcApplication class --- .../main/java/springboot/AepcApplication.java | 49 +++++++++++++------ 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/backend/src/main/java/springboot/AepcApplication.java b/backend/src/main/java/springboot/AepcApplication.java index f74ae898..a5e24c3f 100644 --- a/backend/src/main/java/springboot/AepcApplication.java +++ b/backend/src/main/java/springboot/AepcApplication.java @@ -1,5 +1,8 @@ package springboot; +import java.util.Arrays; +import java.util.List; + import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.FilterRegistrationBean; @@ -7,37 +10,51 @@ import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; + import springboot.config.TokenFilter; @SpringBootApplication public class AepcApplication { + private static final List PROTECTED_URL_PATTERNS = Arrays.asList( + "/api/auth/authenticate/*", + "/api/listaquestoes/*", + "/api/questao/*", + "/api/competencias/*", + "/api/usuario/*", + "/api/avaliacao/*", + "/api/conteudo/*", + "/api/updateClassificador", + "/api/cursoAvaliacao/*", + "/api/cursoCriacao/*", + "/api/cursos/*"); + + /** + * Registra o filtro JWT para proteger rotas específicas. + * + * @return Configuração do filtro de autenticação JWT. + */ @Bean - public FilterRegistrationBean filterJwt() { - FilterRegistrationBean filterRb = new FilterRegistrationBean(); + public FilterRegistrationBean filterJwt() { + FilterRegistrationBean filterRb = new FilterRegistrationBean<>(); filterRb.setFilter(new TokenFilter()); - filterRb.addUrlPatterns( - "/api/auth/authenticate/*", - "/api/listaquestoes/*", - "/api/questao/*", - "/api/competencias/*", - "/api/usuario/*", - "/api/avaliacao/*", - "/api/conteudo/*", - "/api/updateClassificador", - "/api/cursoAvaliacao/*", - "/api/cursoCriacao/*", - "/api/cursos/*"); + filterRb.setUrlPatterns(PROTECTED_URL_PATTERNS); return filterRb; } + /** + * Configura o filtro de CORS para permitir acessos de diferentes origens. + * + * @return Configuração do filtro CORS. + */ @Bean - public FilterRegistrationBean corsFilter() { + public FilterRegistrationBean corsFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration config = new CorsConfiguration().applyPermitDefaultValues(); config.addAllowedMethod("*"); source.registerCorsConfiguration("/**", config); - FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source)); + + FilterRegistrationBean bean = new FilterRegistrationBean<>(new CorsFilter(source)); bean.setOrder(0); return bean; } From 4b019a7353b22fee3df71daa401d9f660f9dbb67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Vitor?= Date: Tue, 17 Sep 2024 02:20:24 -0300 Subject: [PATCH 03/18] update config files --- .vscode/settings.json | 3 + backend/pom.xml | 115 +++++--------- backend/pom.xml.versionsBackup | 97 ++++++++++++ .../SpringWebSecurityInitializer.java | 0 .../java/springboot/config/CorsConfig.java | 61 ++++---- .../springboot/config/DatabaseConfig.java | 18 ++- .../java/springboot/config/SwaggerConfig.java | 79 ---------- .../java/springboot/config/TokenFilter.java | 147 +++++++++++++----- .../springboot/config/ValidatorsConfig.java | 26 +++- .../security/AepcUserDetailsService.java | 0 .../springboot/security/UsuarioSistema.java | 0 backend/src/main/resources/data.json | 40 ++--- backend/src/main/resources/swagger.properties | 0 backend/src/test/resources/test.properties | 0 14 files changed, 323 insertions(+), 263 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 backend/pom.xml.versionsBackup delete mode 100644 backend/src/main/java/springboot/SpringWebSecurityInitializer.java delete mode 100644 backend/src/main/java/springboot/config/SwaggerConfig.java delete mode 100644 backend/src/main/java/springboot/security/AepcUserDetailsService.java delete mode 100644 backend/src/main/java/springboot/security/UsuarioSistema.java delete mode 100644 backend/src/main/resources/swagger.properties delete mode 100644 backend/src/test/resources/test.properties diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..e0f15db2 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "java.configuration.updateBuildConfiguration": "automatic" +} \ No newline at end of file diff --git a/backend/pom.xml b/backend/pom.xml index eb380fd5..70bf905e 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -15,18 +15,17 @@ org.springframework.boot spring-boot-starter-parent - 2.0.4.RELEASE + 3.3.3 UTF-8 UTF-8 - 1.8 + 21 - org.springframework.boot spring-boot-starter-thymeleaf @@ -35,48 +34,14 @@ org.springframework spring-webmvc - - - org.hibernate - hibernate-validator - 5.3.4.Final - - - - - - org.hibernate.ogm - hibernate-ogm-mongodb - 5.3.1.Final - - org.springframework.boot spring-boot-starter-web - - - org.springframework.boot spring-boot-starter-data-mongodb - 3.3.0 - - - - - io.springfox - springfox-swagger-ui - 2.9.2 - - - - io.springfox - springfox-swagger2 - 2.9.2 - - org.springframework.boot spring-boot-devtools @@ -94,64 +59,58 @@ spring-boot-starter-mail - com.google.api-client - google-api-client - 1.30.2 + org.springframework.data + spring-data-jpa + - javax.xml.bind - jaxb-api - 2.3.0 + org.hibernate.validator + hibernate-validator + - com.sun.xml.bind - jaxb-core - 2.3.0 + org.hibernate.ogm + hibernate-ogm-mongodb + 5.4.1.Final + + + org.mongodb + mongo-java-driver + + - com.sun.xml.bind - jaxb-impl - 2.3.0 + org.springdoc + springdoc-openapi-starter-webmvc-ui + 2.6.0 - + - net.htmlparser.jericho - jericho-html - 3.1 + com.google.api-client + google-api-client + 1.33.0 + - io.jsonwebtoken - jjwt - 0.7.0 + net.htmlparser.jericho + jericho-html + 3.4 - + - org.projectlombok - lombok - 1.18.8 + javax.servlet + javax.servlet-api + 4.0.1 provided - - - io.springfox - springfox-bean-validators - 2.9.2 - - - - org.springframework.data - spring-data-jpa - 2.2.0.RELEASE + org.mongodb + mongodb-driver-sync - - com.fasterxml.jackson.core - jackson-databind - 2.9.8 + org.mongodb + mongodb-driver-core - - @@ -162,6 +121,4 @@ - - \ No newline at end of file diff --git a/backend/pom.xml.versionsBackup b/backend/pom.xml.versionsBackup new file mode 100644 index 00000000..774e62ec --- /dev/null +++ b/backend/pom.xml.versionsBackup @@ -0,0 +1,97 @@ + + + 4.0.0 + + springboot + aepc-initializr + 0.0.1-SNAPSHOT + jar + + aepc + Demo project for Spring Boot + + + org.springframework.boot + spring-boot-starter-parent + 3.2.0 + + + + + UTF-8 + UTF-8 + 21 + + + + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-data-mongodb + + + io.springfox + springfox-boot-starter + 3.0.0 + + + org.springframework.boot + spring-boot-devtools + runtime + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.boot + spring-boot-starter-mail + + + com.fasterxml.jackson.core + jackson-databind + + + org.projectlombok + lombok + 1.18.28 + provided + + + io.jsonwebtoken + jjwt-api + 0.11.5 + + + io.jsonwebtoken + jjwt-impl + 0.11.5 + runtime + + + io.jsonwebtoken + jjwt-jackson + 0.11.5 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + \ No newline at end of file diff --git a/backend/src/main/java/springboot/SpringWebSecurityInitializer.java b/backend/src/main/java/springboot/SpringWebSecurityInitializer.java deleted file mode 100644 index e69de29b..00000000 diff --git a/backend/src/main/java/springboot/config/CorsConfig.java b/backend/src/main/java/springboot/config/CorsConfig.java index cb5e60fe..de7f123b 100644 --- a/backend/src/main/java/springboot/config/CorsConfig.java +++ b/backend/src/main/java/springboot/config/CorsConfig.java @@ -1,37 +1,30 @@ package springboot.config; -import java.io.IOException; - -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletResponse; - -import org.springframework.stereotype.Component; - -@Component - public class CorsConfig implements Filter { - - @Override - public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { - HttpServletResponse response = (HttpServletResponse) res; - response.setHeader("Access-Control-Allow-Origin", "*"); - response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE, PATCH"); - response.setHeader("Access-Control-Max-Age", "3600"); - response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); - response.setHeader("Access-Control-Expose-Headers", "Location"); - chain.doFilter(req, res); - }; - - @Override - public void init(FilterConfig filterConfig) {}; - - @Override - public void destroy() {}; - - +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + * Configuração CORS para a aplicação Spring Boot. Esta classe define as regras + * de compartilhamento de recursos entre origens diferentes (Cross-Origin + * Resource Sharing) para permitir que o front-end e back-end comuniquem-se de + * forma segura quando hospedados em domínios distintos. + */ +@Configuration +public class CorsConfig implements WebMvcConfigurer { + + /** + * Configura as regras de CORS para toda a aplicação. + * + * @param registry O registro de configurações CORS. + */ + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") + .allowedOrigins("*") + .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH") + .allowedHeaders("Origin", "X-Requested-With", "Content-Type", "Accept") + .exposedHeaders("Location") + .maxAge(3600); + } } - diff --git a/backend/src/main/java/springboot/config/DatabaseConfig.java b/backend/src/main/java/springboot/config/DatabaseConfig.java index ca8aa952..c26eb57a 100644 --- a/backend/src/main/java/springboot/config/DatabaseConfig.java +++ b/backend/src/main/java/springboot/config/DatabaseConfig.java @@ -6,13 +6,27 @@ import org.springframework.core.io.Resource; import org.springframework.data.repository.init.Jackson2RepositoryPopulatorFactoryBean; +/** + * Configuração para popular o banco de dados com dados iniciais a partir de um + * arquivo JSON localizado no classpath. + */ @Configuration public class DatabaseConfig { + /** + * Cria um bean que popula automaticamente o banco de dados com dados iniciais + * do arquivo "data.json" localizado no classpath. + * + * @return Jackson2RepositoryPopulatorFactoryBean configurado com o recurso + * JSON. + */ @Bean - public Jackson2RepositoryPopulatorFactoryBean getRespositoryPopulator() { + public Jackson2RepositoryPopulatorFactoryBean repositoryPopulator() { Jackson2RepositoryPopulatorFactoryBean factory = new Jackson2RepositoryPopulatorFactoryBean(); - factory.setResources(new Resource[]{new ClassPathResource("data.json")}); + + Resource dataSource = new ClassPathResource("data.json"); + + factory.setResources(new Resource[] { dataSource }); return factory; } } diff --git a/backend/src/main/java/springboot/config/SwaggerConfig.java b/backend/src/main/java/springboot/config/SwaggerConfig.java deleted file mode 100644 index 64edc0ed..00000000 --- a/backend/src/main/java/springboot/config/SwaggerConfig.java +++ /dev/null @@ -1,79 +0,0 @@ -package springboot.config; - -import com.google.common.base.Predicates; -import com.google.common.collect.Lists; -import org.springframework.context.annotation.*; - -import org.springframework.http.ResponseEntity; -import springboot.controller.EmailController; -import springboot.controller.QuestaoController; -import springboot.controller.UsuarioController; -import springfox.documentation.builders.ApiInfoBuilder; -import springfox.documentation.builders.PathSelectors; -import springfox.documentation.service.ApiInfo; -import springfox.documentation.service.ApiKey; -import springfox.documentation.service.AuthorizationScope; -import springfox.documentation.service.SecurityReference; -import springfox.documentation.spi.DocumentationType; -import springfox.documentation.spi.service.contexts.SecurityContext; -import springfox.documentation.spring.web.plugins.Docket; -import springfox.documentation.swagger2.annotations.EnableSwagger2; - -import java.util.List; - -import static springfox.documentation.builders.PathSelectors.regex; - -@EnableSwagger2 -@Import(springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration.class) -@Configuration -public class SwaggerConfig { - - private static final String SWAGGER_API_VERSION = "1.0"; - private static final String LICENSE_TEXT = "License"; - private static final String title = "Ambiente de Estudo sobre o Pensamento Computacional REST API"; - private static final String description = "RESTful API para ComPensar"; - private static final String DEFAULT_INCLUDE_PATTERN = "/api.*"; - - private ApiInfo apiInfo() { - return new ApiInfoBuilder().title(title).description(description).license(LICENSE_TEXT) - .version(SWAGGER_API_VERSION).build(); - } - - @Bean - public Docket swaggerSpringfoxDocket() { - return new Docket(DocumentationType.SWAGGER_2) - .apiInfo(apiInfo()) - .pathMapping("/") - .forCodeGeneration(true) - .genericModelSubstitutes(ResponseEntity.class) - .securityContexts(Lists.newArrayList(securityContext())) - .securitySchemes(Lists.newArrayList(apiKey())) - .useDefaultResponseMessages(false) - .select() - .paths(Predicates.not(regex("/error.*"))) - .paths(regex(DEFAULT_INCLUDE_PATTERN)) - .build(); - } - - - private ApiKey apiKey() { - return new ApiKey("JWT", "Authorization", "header"); - } - - private SecurityContext securityContext() { - return SecurityContext.builder() - .securityReferences(defaultAuth()) - .forPaths(regex(DEFAULT_INCLUDE_PATTERN)) - .build(); - } - - List defaultAuth() { - AuthorizationScope authorizationScope - = new AuthorizationScope("global", "accessEverything"); - AuthorizationScope[] authorizationScopes = new AuthorizationScope[1]; - authorizationScopes[0] = authorizationScope; - return Lists.newArrayList( - new SecurityReference("JWT", authorizationScopes)); - } - -} diff --git a/backend/src/main/java/springboot/config/TokenFilter.java b/backend/src/main/java/springboot/config/TokenFilter.java index f096aee5..884f32ec 100644 --- a/backend/src/main/java/springboot/config/TokenFilter.java +++ b/backend/src/main/java/springboot/config/TokenFilter.java @@ -1,76 +1,137 @@ package springboot.config; +import java.io.IOException; +import java.util.Date; -import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; import org.springframework.http.HttpStatus; -import org.springframework.web.context.WebApplicationContext; -import org.springframework.web.context.support.SpringBeanAutowiringSupport; import org.springframework.web.context.support.WebApplicationContextUtils; import org.springframework.web.filter.GenericFilterBean; + +import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken; +import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken.Payload; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import springboot.service.UsuarioService; import springboot.util.GoogleIdVerifier; -import javax.servlet.*; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.Date; - public class TokenFilter extends GenericFilterBean { @Autowired - UsuarioService usuarioService; + private UsuarioService usuarioService; @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { - if(usuarioService == null){ - ServletContext servletContext = request.getServletContext(); - WebApplicationContext webApplicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext); - usuarioService = webApplicationContext.getBean(UsuarioService.class); + + if (usuarioService == null) { + ApplicationContext ctx = WebApplicationContextUtils + .getRequiredWebApplicationContext(this.getServletContext()); + usuarioService = ctx.getBean(UsuarioService.class); } - HttpServletRequest req = (HttpServletRequest) request; + HttpServletRequest httpRequest = (HttpServletRequest) request; + HttpServletResponse httpResponse = (HttpServletResponse) response; - String header = req.getHeader("Authorization"); + String token = extractToken(httpRequest); + if (token == null) { + sendErrorResponse(httpResponse, HttpStatus.BAD_REQUEST, "Token inválido ou expirado!"); + return; + } - if(header == null || !header.startsWith("Bearer ")) { - ((HttpServletResponse) response).sendError(HttpStatus.BAD_REQUEST.value(), "Token inválido ou expirado!"); + GoogleIdToken.Payload payload = validateToken(token, httpResponse); + if (payload == null) { return; } - // Extraindo apenas o token do cabecalho. - String token = header.substring(7); - GoogleIdToken.Payload payload; + if (!isUserRegistered(payload.getEmail(), httpResponse)) { + return; + } + request.setAttribute("usuario", usuarioService.getById(payload.getEmail())); + chain.doFilter(request, response); + } + + /** + * Extrai o token JWT do cabeçalho "Authorization". + * + * @param request a requisição HTTP + * @return o token JWT, ou null se o cabeçalho não estiver presente ou mal + * formatado + */ + private String extractToken(HttpServletRequest request) { + String header = request.getHeader("Authorization"); + if (header != null && header.startsWith("Bearer ")) { + return header.substring(7); + } + return null; + } + + /** + * Valida o token JWT usando o GoogleIdVerifier. + * + * @param token o token JWT a ser validado + * @param response a resposta HTTP para enviar erros, se necessário + * @return o payload do token se for válido, ou null caso contrário + * @throws IOException + */ + private GoogleIdToken.Payload validateToken(String token, HttpServletResponse response) throws IOException { try { - payload = GoogleIdVerifier.getPayload(token); - System.out.println(new Date(payload.getExpirationTimeSeconds()*1000)); - System.out.println(payload.getExpirationTimeSeconds()); - /* - if (new Random().nextInt(10) > 8) { - System.out.println("Simula expirado"); - throw new Exception(); - }*/ - if (new Date().getTime() > payload.getExpirationTimeSeconds()*1000) { - throw new Exception(); + Payload payload = GoogleIdVerifier.getPayload(token); + if (isTokenExpired(payload)) { + sendErrorResponse(response, HttpStatus.BAD_REQUEST, "Token inválido ou expirado!"); + return null; } - } catch (Exception e) { - ((HttpServletResponse) response).sendError(HttpStatus.BAD_REQUEST.value(), "Token inválido ou expirado!"); - return; + return payload; + } catch (IOException e) { + sendErrorResponse(response, HttpStatus.BAD_REQUEST, "Token inválido ou expirado!"); + return null; } - - String email = payload.getEmail(); + } + + /** + * Verifica se o token JWT expirou. + * + * @param payload o payload do token JWT + * @return true se o token expirou, false caso contrário + */ + private boolean isTokenExpired(GoogleIdToken.Payload payload) { + return new Date().getTime() > payload.getExpirationTimeSeconds() * 1000; + } + + /** + * Verifica se o usuário está registrado no sistema. + * + * @param email o e-mail do usuário + * @param response a resposta HTTP para enviar erros, se necessário + * @return true se o usuário estiver registrado, false caso contrário + * @throws IOException + */ + private boolean isUserRegistered(String email, HttpServletResponse response) throws IOException { try { usuarioService.getById(email); - }catch(Exception e) { - ((HttpServletResponse) response).sendError(HttpStatus.NOT_FOUND.value(), "Usuário ainda não registrado no sistema!"); - return; + return true; + } catch (Exception e) { + sendErrorResponse(response, HttpStatus.NOT_FOUND, "Usuário ainda não registrado no sistema!"); + return false; } - request.setAttribute("usuario", usuarioService.getById(email)); - - chain.doFilter(request, response); } -} \ No newline at end of file + /** + * Envia uma resposta de erro HTTP com o status e a mensagem fornecidos. + * + * @param response a resposta HTTP + * @param status o status HTTP a ser enviado + * @param message a mensagem de erro + * @throws IOException se ocorrer um erro ao enviar a resposta + */ + private void sendErrorResponse(HttpServletResponse response, HttpStatus status, String message) throws IOException { + response.sendError(status.value(), message); + } +} diff --git a/backend/src/main/java/springboot/config/ValidatorsConfig.java b/backend/src/main/java/springboot/config/ValidatorsConfig.java index 74859f79..ffec070d 100644 --- a/backend/src/main/java/springboot/config/ValidatorsConfig.java +++ b/backend/src/main/java/springboot/config/ValidatorsConfig.java @@ -5,19 +5,33 @@ import org.springframework.data.mongodb.core.mapping.event.ValidatingMongoEventListener; import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; -// classes necessárias para as anotações - +/** + * Configuração de validadores para o MongoDB. + * Define os beans necessários para habilitar a validação de documentos usando + * anotações. + */ @Configuration public class ValidatorsConfig { + + /** + * Bean que cria o Listener de Validação para eventos do MongoDB. + * Este listener valida documentos antes de serem persistidos no MongoDB. + * + * @return uma instância de ValidatingMongoEventListener + */ @Bean - public ValidatingMongoEventListener validatingMongoEventListener() { + public ValidatingMongoEventListener mongoEventListener() { return new ValidatingMongoEventListener(validator()); } + /** + * Bean que fornece a fábrica de validadores para o Spring. + * Utiliza a implementação padrão de Bean Validation (JSR-380). + * + * @return uma instância de LocalValidatorFactoryBean + */ @Bean public LocalValidatorFactoryBean validator() { return new LocalValidatorFactoryBean(); } - - -} \ No newline at end of file +} diff --git a/backend/src/main/java/springboot/security/AepcUserDetailsService.java b/backend/src/main/java/springboot/security/AepcUserDetailsService.java deleted file mode 100644 index e69de29b..00000000 diff --git a/backend/src/main/java/springboot/security/UsuarioSistema.java b/backend/src/main/java/springboot/security/UsuarioSistema.java deleted file mode 100644 index e69de29b..00000000 diff --git a/backend/src/main/resources/data.json b/backend/src/main/resources/data.json index 43004e53..2360f1b2 100644 --- a/backend/src/main/resources/data.json +++ b/backend/src/main/resources/data.json @@ -165,13 +165,13 @@ "cursoAvaliacao": { "video": "", "descricao": "", - "exemplos": [], + "videoExemplos": [], "textoExemplos": [] }, "cursoCriacao": { "video": "", "descricao": "", - "exemplos": [], + "videoExemplos": [], "textoExemplos": [] } }, @@ -181,7 +181,7 @@ "cursoAvaliacao": { "video": "https://www.youtube.com/embed/qbnTZCj0ugI?enablejsapi=1", "descricao": "

Texto de exemplo, que pode ser substituído por qualquer texto feito no editor do quill

", - "exemplos": [ + "videoExemplos": [ "https://www.youtube.com/embed/qpxLusH4quY?enablejsapi=1", "https://www.youtube.com/embed/mUXo-S7gzds?enablejsapi=1", "https://www.youtube.com/embed/6hfOvs8pY1k?enablejsapi=1" @@ -195,7 +195,7 @@ "cursoCriacao": { "video": "https://www.youtube.com/embed/qbnTZCj0ugI?enablejsapi=1", "descricao": "

Texto de exemplo, que pode ser substituído por qualquer texto feito no editor do quill

", - "exemplos": [ + "videoExemplos": [ "https://www.youtube.com/embed/qpxLusH4quY?enablejsapi=1", "https://www.youtube.com/embed/mUXo-S7gzds?enablejsapi=1", "https://www.youtube.com/embed/6hfOvs8pY1k?enablejsapi=1" @@ -213,7 +213,7 @@ "cursoAvaliacao": { "video": "https://www.youtube.com/embed/qbnTZCj0ugI?enablejsapi=1", "descricao": "

Texto de exemplo, que pode ser substituído por qualquer texto feito no editor do quill

", - "exemplos": [ + "videoExemplos": [ "https://www.youtube.com/embed/qpxLusH4quY?enablejsapi=1", "https://www.youtube.com/embed/mUXo-S7gzds?enablejsapi=1", "https://www.youtube.com/embed/6hfOvs8pY1k?enablejsapi=1" @@ -227,7 +227,7 @@ "cursoCriacao": { "video": "https://www.youtube.com/embed/qbnTZCj0ugI?enablejsapi=1", "descricao": "

Texto de exemplo, que pode ser substituído por qualquer texto feito no editor do quill

", - "exemplos": [ + "videoExemplos": [ "https://www.youtube.com/embed/qpxLusH4quY?enablejsapi=1", "https://www.youtube.com/embed/mUXo-S7gzds?enablejsapi=1", "https://www.youtube.com/embed/6hfOvs8pY1k?enablejsapi=1" @@ -244,7 +244,7 @@ "nome": "COMP_ANÁLISE", "cursoAvaliacao": { "descricao": "

Texto de exemplo, que pode ser substituído por qualquer texto feito no editor do quill

", - "exemplos": [ + "videoExemplos": [ "https://www.youtube.com/embed/qpxLusH4quY?enablejsapi=1", "https://www.youtube.com/embed/mUXo-S7gzds?enablejsapi=1", "https://www.youtube.com/embed/6hfOvs8pY1k?enablejsapi=1" @@ -258,7 +258,7 @@ "cursoCriacao": { "video": "https://www.youtube.com/embed/qbnTZCj0ugI?enablejsapi=1", "descricao": "

Texto de exemplo, que pode ser substituído por qualquer texto feito no editor do quill

", - "exemplos": [ + "videoExemplos": [ "https://www.youtube.com/embed/qpxLusH4quY?enablejsapi=1", "https://www.youtube.com/embed/mUXo-S7gzds?enablejsapi=1", "https://www.youtube.com/embed/6hfOvs8pY1k?enablejsapi=1" @@ -276,7 +276,7 @@ "cursoAvaliacao": { "video": "https://www.youtube.com/embed/qbnTZCj0ugI?enablejsapi=1", "descricao": "

Texto de exemplo, que pode ser substituído por qualquer texto feito no editor do quill

", - "exemplos": [ + "videoExemplos": [ "https://www.youtube.com/embed/qpxLusH4quY?enablejsapi=1", "https://www.youtube.com/embed/mUXo-S7gzds?enablejsapi=1", "https://www.youtube.com/embed/6hfOvs8pY1k?enablejsapi=1" @@ -290,7 +290,7 @@ "cursoCriacao": { "video": "https://www.youtube.com/embed/qbnTZCj0ugI?enablejsapi=1", "descricao": "

Texto de exemplo, que pode ser substituído por qualquer texto feito no editor do quill

", - "exemplos": [ + "videoExemplos": [ "https://www.youtube.com/embed/qpxLusH4quY?enablejsapi=1", "https://www.youtube.com/embed/mUXo-S7gzds?enablejsapi=1", "https://www.youtube.com/embed/6hfOvs8pY1k?enablejsapi=1" @@ -308,7 +308,7 @@ "cursoAvaliacao": { "video": "https://www.youtube.com/embed/qbnTZCj0ugI?enablejsapi=1", "descricao": "

Texto de exemplo, que pode ser substituído por qualquer texto feito no editor do quill

", - "exemplos": [ + "videoExemplos": [ "https://www.youtube.com/embed/qpxLusH4quY?enablejsapi=1", "https://www.youtube.com/embed/mUXo-S7gzds?enablejsapi=1", "https://www.youtube.com/embed/6hfOvs8pY1k?enablejsapi=1" @@ -322,7 +322,7 @@ "cursoCriacao": { "video": "https://www.youtube.com/embed/qbnTZCj0ugI?enablejsapi=1", "descricao": "

Texto de exemplo, que pode ser substituído por qualquer texto feito no editor do quill

", - "exemplos": [ + "videoExemplos": [ "https://www.youtube.com/embed/qpxLusH4quY?enablejsapi=1", "https://www.youtube.com/embed/mUXo-S7gzds?enablejsapi=1", "https://www.youtube.com/embed/6hfOvs8pY1k?enablejsapi=1" @@ -340,7 +340,7 @@ "cursoAvaliacao": { "video": "", "descricao": "

Texto de exemplo, que pode ser substituído por qualquer texto feito no editor do quill

", - "exemplos": [ + "videoExemplos": [ "https://www.youtube.com/embed/qpxLusH4quY?enablejsapi=1", "https://www.youtube.com/embed/mUXo-S7gzds?enablejsapi=1", "https://www.youtube.com/embed/6hfOvs8pY1k?enablejsapi=1" @@ -354,7 +354,7 @@ "cursoCriacao": { "video": "https://www.youtube.com/embed/qbnTZCj0ugI?enablejsapi=1", "descricao": "

Texto de exemplo, que pode ser substituído por qualquer texto feito no editor do quill

", - "exemplos": [ + "videoExemplos": [ "https://www.youtube.com/embed/qpxLusH4quY?enablejsapi=1", "https://www.youtube.com/embed/mUXo-S7gzds?enablejsapi=1", "https://www.youtube.com/embed/6hfOvs8pY1k?enablejsapi=1" @@ -372,7 +372,7 @@ "cursoAvaliacao": { "video": "https://www.youtube.com/embed/qbnTZCj0ugI?enablejsapi=1", "descricao": "

Texto de exemplo, que pode ser substituído por qualquer texto feito no editor do quill

", - "exemplos": [ + "videoExemplos": [ "https://www.youtube.com/embed/qpxLusH4quY?enablejsapi=1", "https://www.youtube.com/embed/mUXo-S7gzds?enablejsapi=1", "https://www.youtube.com/embed/6hfOvs8pY1k?enablejsapi=1" @@ -386,7 +386,7 @@ "cursoCriacao": { "video": "https://www.youtube.com/embed/qbnTZCj0ugI?enablejsapi=1", "descricao": "

Texto de exemplo, que pode ser substituído por qualquer texto feito no editor do quill

", - "exemplos": [ + "videoExemplos": [ "https://www.youtube.com/embed/qpxLusH4quY?enablejsapi=1", "https://www.youtube.com/embed/mUXo-S7gzds?enablejsapi=1", "https://www.youtube.com/embed/6hfOvs8pY1k?enablejsapi=1" @@ -404,7 +404,7 @@ "cursoAvaliacao": { "video": "https://www.youtube.com/embed/qbnTZCj0ugI?enablejsapi=1", "descricao": "

Texto de exemplo, que pode ser substituído por qualquer texto feito no editor do quill

", - "exemplos": [ + "videoExemplos": [ "https://www.youtube.com/embed/qpxLusH4quY?enablejsapi=1", "https://www.youtube.com/embed/mUXo-S7gzds?enablejsapi=1", "https://www.youtube.com/embed/6hfOvs8pY1k?enablejsapi=1" @@ -418,7 +418,7 @@ "cursoCriacao": { "video": "https://www.youtube.com/embed/qbnTZCj0ugI?enablejsapi=1", "descricao": "

Texto de exemplo, que pode ser substituído por qualquer texto feito no editor do quill

", - "exemplos": [ + "videoExemplos": [ "https://www.youtube.com/embed/qpxLusH4quY?enablejsapi=1", "https://www.youtube.com/embed/mUXo-S7gzds?enablejsapi=1", "https://www.youtube.com/embed/6hfOvs8pY1k?enablejsapi=1" @@ -436,7 +436,7 @@ "cursoAvaliacao": { "video": null, "descricao": "

Texto de exemplo, que pode ser substituído por qualquer texto feito no editor do quill

", - "exemplos": [ + "videoExemplos": [ "https://www.youtube.com/embed/qpxLusH4quY?enablejsapi=1", "https://www.youtube.com/embed/mUXo-S7gzds?enablejsapi=1", "https://www.youtube.com/embed/6hfOvs8pY1k?enablejsapi=1" @@ -450,7 +450,7 @@ "cursoCriacao": { "video": "https://www.youtube.com/embed/qbnTZCj0ugI?enablejsapi=1", "descricao": "

Texto de exemplo, que pode ser substituído por qualquer texto feito no editor do quill

", - "exemplos": [ + "videoExemplos": [ "https://www.youtube.com/embed/qpxLusH4quY?enablejsapi=1", "https://www.youtube.com/embed/mUXo-S7gzds?enablejsapi=1", "https://www.youtube.com/embed/6hfOvs8pY1k?enablejsapi=1" diff --git a/backend/src/main/resources/swagger.properties b/backend/src/main/resources/swagger.properties deleted file mode 100644 index e69de29b..00000000 diff --git a/backend/src/test/resources/test.properties b/backend/src/test/resources/test.properties deleted file mode 100644 index e69de29b..00000000 From 9c104c58258e52bb8dee8b4b469bfb0c690329cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Vitor?= Date: Tue, 17 Sep 2024 02:31:28 -0300 Subject: [PATCH 04/18] update controller files --- .../springboot/controller/AuthController.java | 86 +++-- .../controller/AvaliacaoController.java | 124 +++---- .../controller/CursoController.java | 84 ++--- .../controller/EmailController.java | 62 ++-- .../controller/ListaQuestoesController.java | 174 ++++++---- .../controller/QuestaoController.java | 317 +++++++++--------- .../controller/QuestionSearchController.java | 180 +++++----- .../controller/UsuarioController.java | 109 +++--- 8 files changed, 605 insertions(+), 531 deletions(-) diff --git a/backend/src/main/java/springboot/controller/AuthController.java b/backend/src/main/java/springboot/controller/AuthController.java index 2fb93d1e..e78d06d0 100644 --- a/backend/src/main/java/springboot/controller/AuthController.java +++ b/backend/src/main/java/springboot/controller/AuthController.java @@ -1,16 +1,23 @@ package springboot.controller; -import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; +import java.util.Date; + import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; import springboot.dto.input.UsuarioInput; import springboot.dto.output.CustomRestOutput; import springboot.exception.auth.InvalidTokenException; @@ -19,47 +26,56 @@ import springboot.service.UsuarioService; import springboot.util.GoogleIdVerifier; -import java.util.Date; - -@Controller @RestController -@RequestMapping(value = "/api") -@CrossOrigin(origins = "+") -@Api(value = "AuthControllerAPI", produces = MediaType.APPLICATION_JSON_VALUE) +@RequestMapping("/api") +@CrossOrigin(origins = "*") +@Tag(name = "AuthController", description = "API para autenticação e cadastro de usuários") public class AuthController { - private final int HOUR = 60 * 60 * 1000; - @Autowired - UsuarioService usuarioService; + private UsuarioService usuarioService; - @ApiOperation("Permite autenticar um usuário no sistema.\r\n") - @ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = CustomRestOutput.class) }) - @RequestMapping(value = "/auth/authenticate", method = RequestMethod.GET) + @Operation(summary = "Permite autenticar um usuário no sistema") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Usuário autenticado com sucesso!") + }) + @GetMapping("/auth/authenticate") public ResponseEntity authenticate() { - return new ResponseEntity<>(new CustomRestOutput(new Date(), "Usuário autenticado com sucesso!"), HttpStatus.OK); + return ResponseEntity.ok(new CustomRestOutput(new Date(), "Usuário autenticado com sucesso!")); } + @Operation(summary = "Permite cadastrar um usuário no sistema") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Usuário cadastrado com sucesso!"), + @ApiResponse(responseCode = "400", description = "Token inválido"), + @ApiResponse(responseCode = "409", description = "Usuário já existe") + }) + @PostMapping("/auth/signup") + public ResponseEntity signup(@RequestBody UsuarioInput usuario, + @RequestHeader("Authorization") String token) { + validateToken(token); - @ApiOperation("Permite cadastrar um usuário no sistema.\r\n") - @ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = CustomRestOutput.class) }) - @RequestMapping(value = "/auth/signup", method = RequestMethod.POST) - public ResponseEntity signup(@RequestBody UsuarioInput usuario, @RequestHeader("Authorization") String token) { - if(token == null || !token.startsWith("Bearer ")) { - throw new InvalidTokenException(); - } - - GoogleIdToken.Payload payload = GoogleIdVerifier.getPayload(token.substring(7)); - + GoogleIdToken.Payload payload = GoogleIdVerifier.getPayload(extractToken(token)); String email = payload.getEmail(); String nome = (String) payload.get("name"); - try { usuarioService.getById(email); throw new UserAlreadyExistException(); } catch (Exception e) { - usuarioService.save(new Usuario(nome, usuario.getIdade(), usuario.getNomeInstituicao(), usuario.getCargo(), usuario.getCidade(), email, true)); + usuarioService.save(new Usuario(nome, usuario.getIdade(), usuario.getNomeInstituicao(), usuario.getCargo(), + usuario.getCidade(), email, true)); + } + + return ResponseEntity.ok(new CustomRestOutput(new Date(), "Usuário cadastrado com sucesso!")); + } + + private String extractToken(String token) { + return token.substring(7); // Remove "Bearer " + } + + private void validateToken(String token) { + if (token == null || !token.startsWith("Bearer ")) { + throw new InvalidTokenException(); } - return new ResponseEntity<>(new CustomRestOutput(new Date(), "Usuário autenticado com sucesso!"), HttpStatus.OK); } } diff --git a/backend/src/main/java/springboot/controller/AvaliacaoController.java b/backend/src/main/java/springboot/controller/AvaliacaoController.java index 493a8728..dc0eab8d 100644 --- a/backend/src/main/java/springboot/controller/AvaliacaoController.java +++ b/backend/src/main/java/springboot/controller/AvaliacaoController.java @@ -1,15 +1,27 @@ package springboot.controller; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; +import java.io.IOException; +import java.util.HashSet; +import java.util.List; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestAttribute; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.tags.Tag; + +import jakarta.validation.Valid; import springboot.dto.input.AvaliacaoInput; import springboot.enums.CompetenciaType; import springboot.enums.EstadoQuestao; @@ -19,28 +31,35 @@ import springboot.service.AvaliacaoService; import springboot.service.QuestaoService; -import java.io.IOException; -import java.util.HashSet; -import java.util.List; - -@Controller @RestController @RequestMapping(value = "/api") -@CrossOrigin(origins = "+") -@Api(value = "AvaliacaoControllerAPI", produces = MediaType.APPLICATION_JSON_VALUE) +@CrossOrigin(origins = "*") +@Tag(name = "AvaliacaoController", description = "API para gerenciar avaliações") public class AvaliacaoController { @Autowired - AvaliacaoService avaliacaoService; + private AvaliacaoService avaliacaoService; @Autowired - QuestaoService questaoService; + private QuestaoService questaoService; + + @Operation(summary = "Permite registrar uma nova avaliação no sistema.") + @ApiResponses(value = { + @ApiResponse(responseCode = "201", description = "Avaliação criada com sucesso", + content = @Content(mediaType = "application/json", + schema = @Schema(implementation = Avaliacao.class))), + @ApiResponse(responseCode = "404", description = "Questão não encontrada", content = @Content), + @ApiResponse(responseCode = "400", description = "Erro de validação", content = @Content) + }) + @PostMapping("/avaliacao") + public ResponseEntity save(@RequestAttribute(name = "usuario") Usuario usuario, + @Valid @RequestBody AvaliacaoInput avaliacao) throws IOException { + + Questao questao = questaoService.getById(avaliacao.getQuestaoId()); + if (questao == null) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).build(); + } - @ApiOperation("Permite registrar uma nova avaliação no sistema. Requer que o corpo do request contenha um objeto com os campos: observacoes, questao e competencias.\r\n") - @ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = Avaliacao.class) }) - @RequestMapping(value = "/avaliacao", method = RequestMethod.POST) - public Avaliacao save(@RequestAttribute(name="usuario") Usuario usuario, @RequestBody AvaliacaoInput avaliacao) throws IOException { - Questao questao = questaoService.getById(avaliacao.getQuestao()); Avaliacao novaAvaliacao = avaliacaoService.save( new Avaliacao( avaliacao.getObservacaoAvaliacao(), @@ -50,51 +69,36 @@ public Avaliacao save(@RequestAttribute(name="usuario") Usuario usuario, @Reques usuario.getEmail(), questao.getId(), avaliacao.getConfianca(), - avaliacao.getAvaliacaoPublicacao() - ) - ); - questao.setQtdAvaliacoes(questao.getQtdAvaliacoes()+1); + avaliacao.getAvaliacaoPublicacao())); + + questao.setQtdAvaliacoes(questao.getQtdAvaliacoes() + 1); + if (questao.getQtdAvaliacoes() == 3) { - HashSet tempNewCompetencias = new HashSet<>(); - List avaliacoes = avaliacaoService.getAllByQuestao(avaliacao.getQuestao()); - for (CompetenciaType competencia: CompetenciaType.values()) { - int cnt = 0; - for (Avaliacao tempAvaliacao : avaliacoes) { - if (tempAvaliacao.getCompetencias().contains(competencia)) - cnt++; - } - if (cnt >= 2) { - tempNewCompetencias.add(competencia); - } - //System.out.println("competencia: "+competencia); - } - questao.setCompetencias(tempNewCompetencias); + HashSet novasCompetencias = calcularCompetenciasComuns(avaliacao.getQuestaoId()); + questao.setCompetencias(novasCompetencias); questao.setEstado(EstadoQuestao.PEND_APROVACAO); } + questaoService.update(questao, questao.getId()); - return novaAvaliacao; - } - /* + return ResponseEntity.status(HttpStatus.CREATED).body(novaAvaliacao); + } - @ApiOperation("Permite atualizar uma avaliação no sistema. Requer que o corpo do request contenha um objeto com os campos: observacoes, questao e competencias.\r\n" - + "") - @ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = Avaliacao.class) }) - @RequestMapping(value = "/avaliacao/{id}", method = RequestMethod.PUT) - public ResponseEntity update(@PathVariable("id") String id, @RequestAttribute(name="usuario") Usuario usuario, @RequestBody AvaliacaoInput avaliacao) { + private HashSet calcularCompetenciasComuns(String questaoId) { + List avaliacoes = avaliacaoService.getAllByQuestao(questaoId); + HashSet competenciasComuns = new HashSet<>(); - Avaliacao updatedAvaliacao = avaliacaoService.update( - new Avaliacao( - avaliacao.getObservacaoAvaliacao(), - avaliacao.getObservacaoQuestao(), - avaliacao.getCompetencias(), - usuario.getEmail(), - avaliacao.getQuestao(), - avaliacao.getConfianca() - ), - id - ); - return new ResponseEntity(updatedAvaliacao, HttpStatus.OK); + for (CompetenciaType competencia : CompetenciaType.values()) { + int contador = 0; + for (Avaliacao avaliacao : avaliacoes) { + if (avaliacao.getCompetencias().contains(competencia)) { + contador++; + } + } + if (contador >= 2) { + competenciasComuns.add(competencia); + } + } + return competenciasComuns; } - */ } diff --git a/backend/src/main/java/springboot/controller/CursoController.java b/backend/src/main/java/springboot/controller/CursoController.java index 797c4fd1..f928ab22 100644 --- a/backend/src/main/java/springboot/controller/CursoController.java +++ b/backend/src/main/java/springboot/controller/CursoController.java @@ -5,12 +5,13 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponses; -import io.swagger.annotations.ApiResponse; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.tags.Tag; -import org.springframework.http.MediaType; import springboot.dto.output.CursoOutput; import springboot.dto.output.ModuloCursoOutput; import springboot.enums.CourseType; @@ -26,9 +27,8 @@ @RestController @RequestMapping(value = "/api") -@CrossOrigin(origins = "+") -@Api(value = "UsuariosControllerAPI", produces = MediaType.APPLICATION_JSON_VALUE) - +@CrossOrigin(origins = "*") +@Tag(name = "CursoController", description = "API para gerenciar cursos") public class CursoController { public static final String COMP_NAMES[] = new String[] { "COMP_ABSTRAÇÃO", @@ -57,9 +57,11 @@ public class CursoController { * @param user Usuário logado no sistema, injetado pelo framework. * @return ResponseEntity contendo o estado atual do curso de avaliação. */ - @ApiOperation("Permite pegar a tela atual do usuário no curso de avaliação.\r\n") - @ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = Usuario.class) }) - @RequestMapping(value = "/cursoAvaliacao/", method = RequestMethod.GET) + @Operation(summary = "Retorna a tela atual do usuário no curso de avaliação.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "OK", content = @Content(mediaType = "application/json", schema = @Schema(implementation = CursoOutput.class))) + }) + @GetMapping(value = "/cursoAvaliacao") public ResponseEntity getReviewCourse(@RequestAttribute(name = "usuario") Usuario user) { return cursoService.auxCursoAvaliacoes(user, null); } @@ -75,9 +77,11 @@ public ResponseEntity getReviewCourse(@RequestAttribute(name = "usu * @return Um ResponseEntity contendo o CursoOutput atualizado e status HTTP de * sucesso. */ - @ApiOperation("Cria novos cursos para o usuário logado.") - @ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = Usuario.class) }) - @GetMapping(value = "/cursos/") + @Operation(summary = "Cria novos cursos para o usuário logado.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "OK", content = @Content(mediaType = "application/json", schema = @Schema(implementation = CursoOutput.class))) + }) + @GetMapping(value = "/cursos") public ResponseEntity newCourses(@RequestAttribute(name = "usuario") Usuario user) { try { if (cursoService.isCourseListEmpty(user.getCursoAvaliacao())) @@ -91,7 +95,7 @@ public ResponseEntity newCourses(@RequestAttribute(name = "usuario" List cursoCriacao = cursoService.processModules(user.getCursoCriacao(), CourseType.CRIACAO, user); - user = usuarioService.update(user, user.getEmail()); + usuarioService.update(user, user.getEmail()); CursoOutput moduleStats = new CursoOutput(null, cursoAvaliacao, cursoCriacao); @@ -109,14 +113,17 @@ public ResponseEntity newCourses(@RequestAttribute(name = "usuario" * @param answers Lista de respostas fornecidas pelo usuário. * @return ResponseEntity contendo o resultado da operação. */ - @ApiOperation("Avança no curso de avaliação para o usuário logado.\r\n") - @ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = Usuario.class) }) - @RequestMapping(value = "/cursoAvaliacao/", method = RequestMethod.POST) + @Operation(summary = "Avança no curso de avaliação para o usuário logado.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "OK", content = @Content(mediaType = "application/json", schema = @Schema(implementation = CursoOutput.class))) + }) + @PostMapping(value = "/cursoAvaliacao") public ResponseEntity advanceReviewCourse(@RequestAttribute(name = "usuario") Usuario user, @RequestBody List answers) { - if (cursoService.isCourseListEmpty(user.getCursoAvaliacao())) - return new ResponseEntity(new CursoOutput(), HttpStatus.NOT_FOUND); + if (cursoService.isCourseListEmpty(user.getCursoAvaliacao())) { + return new ResponseEntity<>(new CursoOutput(), HttpStatus.NOT_FOUND); + } String message = null; @@ -142,12 +149,12 @@ public ResponseEntity advanceReviewCourse(@RequestAttribute(name = * @return ResponseEntity contendo o estado atual do curso de criação * ou um erro caso ocorra alguma falha. */ - @ApiOperation("Obtém a tela atual do usuário no curso de criação de questões.") + @Operation(summary = "Obtém a tela atual do usuário no curso de criação de questões.") @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK", response = CursoOutput.class), - @ApiResponse(code = 404, message = "Curso de criação de questões não encontrado", response = CursoOutput.class) + @ApiResponse(responseCode = "200", description = "OK", content = @Content(mediaType = "application/json", schema = @Schema(implementation = CursoOutput.class))), + @ApiResponse(responseCode = "404", description = "Curso de criação de questões não encontrado", content = @Content(mediaType = "application/json", schema = @Schema(implementation = CursoOutput.class))) }) - @GetMapping("/cursoCriacao/") + @GetMapping("/cursoCriacao") public ResponseEntity getCreationCourse(@RequestAttribute(name = "usuario") Usuario user) { return cursoService.auxCursoCriacao(user, null); } @@ -164,14 +171,17 @@ public ResponseEntity getCreationCourse(@RequestAttribute(name = "u * @param answers Lista de respostas fornecidas pelo usuário. * @return ResponseEntity com o resultado do avanço no curso de criação. */ - @ApiOperation("Avança no curso de criação de questões para o usuário logado.\r\n") - @ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = Usuario.class) }) - @RequestMapping(value = "/cursoCriacao/", method = RequestMethod.POST) + @Operation(summary = "Avança no curso de criação de questões para o usuário logado.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "OK", content = @Content(mediaType = "application/json", schema = @Schema(implementation = CursoOutput.class))) + }) + @PostMapping(value = "/cursoCriacao") public ResponseEntity advanceCreationCourse(@RequestAttribute(name = "usuario") Usuario user, @RequestBody List answers) { - if (cursoService.isCourseListEmpty(user.getCursoCriacao())) - return new ResponseEntity(new CursoOutput(), HttpStatus.NOT_FOUND); + if (cursoService.isCourseListEmpty(user.getCursoCriacao())) { + return new ResponseEntity<>(new CursoOutput(), HttpStatus.NOT_FOUND); + } String message = null; @@ -199,14 +209,16 @@ public ResponseEntity advanceCreationCourse(@RequestAttribute(name * @return ResponseEntity com o resultado do registro da questão no curso de * criação. */ - @ApiOperation("Registra uma nova questão criada na avaliação final do usuário logado.") - @ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = Usuario.class) }) - @RequestMapping(value = "/cursoCriacao/newQuestion", method = RequestMethod.POST) + @Operation(summary = "Registra uma nova questão criada na avaliação final do usuário logado.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "OK", content = @Content(mediaType = "application/json", schema = @Schema(implementation = CursoOutput.class))), + @ApiResponse(responseCode = "404", description = "Questão não encontrada", content = @Content) + }) + @PostMapping(value = "/cursoCriacao/newQuestion") public ResponseEntity registraCriacaoQuestao( @RequestAttribute(name = "usuario") Usuario user, @RequestBody String question) { - // Verifica se o curso de criação do usuário está presente e não está vazio. if (cursoService.isCourseListEmpty(user.getCursoCriacao())) { return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new CursoOutput()); } @@ -214,20 +226,14 @@ public ResponseEntity registraCriacaoQuestao( String message = null; try { - // Verifica se a questão existe no sistema. questaoService.getById(question); - - // Adiciona a questão ao módulo apropriado no curso de criação do usuário. user.getCursoCriacao().get(10).setQuestoes(Collections.singletonList(question)); user = usuarioService.update(user, user.getEmail()); } catch (RegisterNotFoundException e) { - // Define mensagem de erro caso a questão não seja encontrada. message = "A questão especificada não existe."; } - // Retorna o resultado do processamento do curso de criação. return cursoService.auxCursoCriacao(user, message); } - } diff --git a/backend/src/main/java/springboot/controller/EmailController.java b/backend/src/main/java/springboot/controller/EmailController.java index dcd69fa6..159085f7 100644 --- a/backend/src/main/java/springboot/controller/EmailController.java +++ b/backend/src/main/java/springboot/controller/EmailController.java @@ -1,45 +1,45 @@ package springboot.controller; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.mail.SimpleMailMessage; -import org.springframework.mail.javamail.JavaMailSender; -import org.springframework.stereotype.Controller; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.mail.MailException; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.CrossOrigin; +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.RequestMethod; import org.springframework.web.bind.annotation.RestController; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import jakarta.validation.Valid; import springboot.model.Email; - -@Controller +import springboot.service.EmailService; + @RestController -@RequestMapping(value = "/api") -@CrossOrigin(origins = "+") +@RequestMapping("/api") +@CrossOrigin(origins = "*") +@Validated public class EmailController { - + @Autowired - public JavaMailSender emailSender; - - @ApiOperation("Permite registrar um email de um user para o admin.\r\n" - + "") - @ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = Email.class) }) - @RequestMapping(value = "/email", method = RequestMethod.POST) - public void sendSimpleEmail(@RequestBody Email email) { - - // Create a Simple MailMessage. - SimpleMailMessage message = new SimpleMailMessage(); - - message.setTo("aepc.lacina@gmail.com"); - message.setSubject(email.getSubject()); - message.setText("From: " + email.getUsername() + "\n" + email.getMessage()); - message.setReplyTo(email.getEmail() ); - message.setFrom(email.getEmail()); + private EmailService emailService; - // Send Message! - this.emailSender.send(message); + @Operation(summary = "Permite registrar um email de um user para o admin.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Email enviado com sucesso"), + @ApiResponse(responseCode = "400", description = "Erro de validação de entrada"), + @ApiResponse(responseCode = "500", description = "Erro ao enviar o email") + }) + @PostMapping("/email") + public ResponseEntity sendSimpleEmail(@Valid @RequestBody Email email) { + try { + emailService.sendEmail(email); + return ResponseEntity.ok("Email enviado com sucesso!"); + } catch (MailException e) { + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Erro ao enviar o email"); + } } -} \ No newline at end of file +} diff --git a/backend/src/main/java/springboot/controller/ListaQuestoesController.java b/backend/src/main/java/springboot/controller/ListaQuestoesController.java index f7e0ac57..ae280489 100644 --- a/backend/src/main/java/springboot/controller/ListaQuestoesController.java +++ b/backend/src/main/java/springboot/controller/ListaQuestoesController.java @@ -1,99 +1,141 @@ package springboot.controller; -import java.util.ArrayList; -import java.util.List; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; -import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; - -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; import springboot.dto.IO.ListaQuestoesIO; import springboot.dto.input.ListaQuestoesInput; -import springboot.dto.input.QuestaoInput; import springboot.dto.output.ListaQuestoesOutput; import springboot.model.ListaQuestoes; -import springboot.model.Questao; import springboot.model.Usuario; import springboot.service.ListaQuestoesService; -import springboot.service.QuestaoService; import springboot.service.UsuarioService; -@Controller +/** + * Controlador REST para gerenciamento de listas de questões. + * Oferece endpoints para operações de CRUD (criação, leitura, atualização, + * exclusão). + */ @RestController -@RequestMapping(value = "/api") +@RequestMapping("/api") @CrossOrigin(origins = "+") public class ListaQuestoesController { - + @Autowired - ListaQuestoesService listaQuestoesService; + private ListaQuestoesService listaQuestoesService; @Autowired - QuestaoService questaoService; + private UsuarioService usuarioService; @Autowired - UsuarioService usuarioService; + private ListaQuestoesIO listaQuestoesIO; - public ListaQuestoesOutput convert(ListaQuestoes lista) { - return ListaQuestoesIO.convert(lista, usuarioService.getById(lista.getAutor()).getNome(), questaoService); + /** + * Converte uma entidade {@link ListaQuestoes} em um DTO + * {@link ListaQuestoesOutput}. + * + * @param lista a lista de questões a ser convertida + * @return o DTO de saída correspondente + */ + private ListaQuestoesOutput convertToOutput(ListaQuestoes lista) { + String nomeAutor = usuarioService.getById(lista.getAutor()).getNome(); + return listaQuestoesIO.toDto(lista, nomeAutor); } - - @ApiOperation("Permite registrar uma nova lista de questões no sistema. Requer que o corpo do request contenha um objeto com os campos: email e questoes.\r\n" - + "") - @ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = Questao.class) }) - @RequestMapping(value = "/listaquestoes", method = RequestMethod.POST) - public ListaQuestoesOutput save(@RequestAttribute(name="usuario") Usuario usuario, @RequestBody ListaQuestoesInput listaQuestoes) { - return convert(listaQuestoesService.save(ListaQuestoesIO.convert(listaQuestoes, usuario, questaoService))); + + /** + * Registra uma nova lista de questões no sistema. + * + * @param usuario o usuário autenticado que está criando a lista + * @param listaQuestoes os dados da lista de questões a ser criada + * @return a lista de questões criada + */ + @Operation(summary = "Registra uma nova lista de questões no sistema.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "OK") + }) + @PostMapping("/listaquestoes") + public ResponseEntity save(@RequestAttribute(name = "usuario") Usuario usuario, + @RequestBody ListaQuestoesInput listaQuestoes) { + ListaQuestoes listaSalva = listaQuestoesService + .save(listaQuestoesIO.toEntity(listaQuestoes, usuario)); + return ResponseEntity.ok(convertToOutput(listaSalva)); } - - @ApiOperation("Permite apagar uma lista de questões no sistema.") - @ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = Questao.class) }) - @RequestMapping(value = "/listaquestoes/{id}", method = RequestMethod.DELETE) + + /** + * Apaga uma lista de questões do sistema. + * + * @param id o identificador da lista de questões a ser removida + * @return a lista de questões removida + */ + @Operation(summary = "Apaga uma lista de questões no sistema.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "OK") + }) + @DeleteMapping("/listaquestoes/{id}") public ResponseEntity delete(@PathVariable("id") String id) { - ListaQuestoes listaQuestoes = listaQuestoesService.delete(id); - return new ResponseEntity(convert(listaQuestoes), HttpStatus.OK); - } - - @ApiOperation("Permite atualizar uma lista de questões do sistema. Requer que o corpo do request contenha um objeto com os atributos de uma lista de questões.\r\n" - + "") - @ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = Questao.class) }) - @RequestMapping(value = "/listaquestoes/{id}", method = RequestMethod.PUT) - public ResponseEntity update(@PathVariable("id") String id, @RequestAttribute(name="usuario") Usuario usuario, @RequestBody ListaQuestoesInput listaQuestoes) { - ListaQuestoes updatedlistaQuestoes = listaQuestoesService.update(ListaQuestoesIO.convert(listaQuestoes, usuario, questaoService), id); - return new ResponseEntity(convert(updatedlistaQuestoes), HttpStatus.OK); + ListaQuestoes listaRemovida = listaQuestoesService.delete(id); + return ResponseEntity.ok(convertToOutput(listaRemovida)); } - @ApiOperation("Fornece um array de objetos do tipo lista de questões registrados.") - @ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = Questao.class) }) - @RequestMapping(value = "/listaquestoes/{page}/{size}", method = RequestMethod.GET) - public Page getAll(@RequestAttribute(name="usuario") Usuario usuario,@PathVariable("page") int page,@PathVariable("size") int size) { - return listaQuestoesService.getAll(usuario, page, size).map(this::convert); - } - - @ApiOperation("Fornece a lista de questões com o id especificado.") - @ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = Questao.class) }) - @RequestMapping(value = "/listaquestoes/{id}", method = RequestMethod.GET) - public ListaQuestoesOutput getById(@PathVariable("id") String id) { - return convert(listaQuestoesService.getById(id)); + /** + * Atualiza uma lista de questões existente no sistema. + * + * @param id o identificador da lista de questões a ser atualizada + * @param usuario o usuário autenticado que está atualizando a lista + * @param listaQuestoes os novos dados da lista de questões + * @return a lista de questões atualizada + */ + @Operation(summary = "Atualiza uma lista de questões do sistema.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "OK") + }) + @PutMapping("/listaquestoes/{id}") + public ResponseEntity update(@PathVariable("id") String id, + @RequestAttribute(name = "usuario") Usuario usuario, + @RequestBody ListaQuestoesInput listaQuestoes) { + ListaQuestoes listaAtualizada = listaQuestoesService + .update(listaQuestoesIO.toEntity(listaQuestoes, usuario), id); + return ResponseEntity.ok(convertToOutput(listaAtualizada)); } + /** + * Recupera todas as listas de questões com paginação. + * + * @param usuario o usuário autenticado + * @param page o número da página a ser recuperada + * @param size o tamanho da página + * @return uma página contendo listas de questões + */ + @Operation(summary = "Recupera todas as listas de questões com paginação.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "OK") + }) + @GetMapping("/listaquestoes/{page}/{size}") + public ResponseEntity> getAll(@RequestAttribute(name = "usuario") Usuario usuario, + @PathVariable("page") int page, + @PathVariable("size") int size) { + Page pageResult = listaQuestoesService.getAll(usuario, page, size) + .map(this::convertToOutput); + return ResponseEntity.ok(pageResult); + } -/* - @ApiOperation("Fornece os dados de lista de questões registradas por determinado email. \r\n" - + "") - @ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = Questao.class) }) - @RequestMapping(value = "/listaquestoes/{page}/{size}", method = RequestMethod.GET) - public Page getByNomeEmail(@RequestAttribute(name="usuario") Usuario usuario, @PathVariable("email") String email, - @PathVariable("page") int page, @PathVariable("size") int size) { - Page listas = listaQuestoesService.getByUser(usuario,page,size); - return listas.map(ListaQuestoesIO::convert); - + /** + * Recupera uma lista de questões específica pelo ID. + * + * @param id o identificador da lista de questões + * @return a lista de questões correspondente + */ + @Operation(summary = "Recupera uma lista de questões pelo ID.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "OK") + }) + @GetMapping("/listaquestoes/{id}") + public ResponseEntity getById(@PathVariable("id") String id) { + ListaQuestoes listaQuestoes = listaQuestoesService.getById(id); + return ResponseEntity.ok(convertToOutput(listaQuestoes)); } -*/ } diff --git a/backend/src/main/java/springboot/controller/QuestaoController.java b/backend/src/main/java/springboot/controller/QuestaoController.java index 0b78baed..b1911abc 100644 --- a/backend/src/main/java/springboot/controller/QuestaoController.java +++ b/backend/src/main/java/springboot/controller/QuestaoController.java @@ -1,23 +1,14 @@ package springboot.controller; - import java.io.IOException; -import java.util.ArrayList; import java.util.List; import java.util.Set; +import java.util.stream.Collectors; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.domain.Page; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; import springboot.dto.IO.QuestaoIO; import springboot.dto.input.AvaliacaoInput; import springboot.dto.input.QuestaoInput; @@ -27,158 +18,150 @@ import springboot.enums.EstadoQuestao; import springboot.enums.PermissaoType; import springboot.exception.data.PermissionDeniedException; -import springboot.model.Avaliacao; import springboot.model.Conteudo; import springboot.model.Questao; import springboot.model.Usuario; -import springboot.service.AvaliacaoService; import springboot.service.ConteudoService; import springboot.service.QuestaoService; -import springboot.service.UsuarioService; -@Controller +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; + @RestController @RequestMapping(value = "/api") -@CrossOrigin(origins = "+") -@Api(value = "QuestaoControllerAPI", produces = MediaType.APPLICATION_JSON_VALUE) +@CrossOrigin(origins = "*") +@Tag(name = "QuestaoController", description = "Controlador de operações relacionadas a Questões") public class QuestaoController { - - @Autowired - QuestaoService questaoService; - - @Autowired - AvaliacaoController avaliacaoController; - - @Autowired - AvaliacaoService avaliacaoService; - - @Autowired - UsuarioService usuarioService; - - @Autowired - ConteudoService conteudoService; - - private QuestaoOutput convert(Questao questao, Usuario usuario, boolean forceAvaliacoes) { - return QuestaoIO.convert(questao, usuario, usuarioService, avaliacaoService, questaoService, forceAvaliacoes); - } - - @ApiOperation("Permite registrar uma nova questão no sistema. Requer que o corpo do request contenha um objeto com os campos: tipo, enunciado, fonte, autor, imagem, conteudo, espelho ou alternativas.\r\n" - + "") - @ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = Questao.class) }) - @RequestMapping(value = "/questao", method = RequestMethod.POST) - public QuestaoOutput save(@RequestAttribute(name="usuario") Usuario usuario, @RequestBody QuestaoInput questao) throws IOException { - Questao questaoSalva = questaoService.save(QuestaoIO.convert(questao, usuario.getEmail())); - avaliacaoController.save(usuario, - new AvaliacaoInput( - questao.getObsAvaliacao(), - "", - questaoSalva.getId(), - questao.getCompetenciasAvaliacao(), - questao.getInfoCompetenciasAvaliacao(), - questao.getConfiancaAvaliacao(), - AvaliacaoPublicacao.PRONTA - ) - ); - return convert(questaoSalva, usuario, false); - } - - @ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = Conteudo.class) }) - @RequestMapping(value = "/conteudo", method = RequestMethod.POST) - public Conteudo saveConteudo(@RequestBody String conteudo) throws IOException { - conteudoService.save(new Conteudo(conteudo)); - return new Conteudo(conteudo); - } - - @ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = Conteudo.class) }) - @RequestMapping(value = "/conteudo", method = RequestMethod.GET) - public ResponseEntity> getAllConteudo() throws IOException { - List l = new ArrayList<>(); - for (Conteudo conteudoItem : conteudoService.getAll()) { - if (!conteudoItem.getNome().equals("Outros")) - l.add(conteudoItem.getNome()); - } - l.add("Outros"); - - return new ResponseEntity>(l, HttpStatus.OK); - } - - @ApiOperation("Permite apagar uma questão do sistema.") - @ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = Questao.class) }) - @RequestMapping(value = "/questao/{id}", method = RequestMethod.DELETE) - public ResponseEntity delete(@RequestAttribute(name="usuario") Usuario usuario, @PathVariable("id") String id) { - Questao questao = questaoService.getById(id); - if (!questao.getAutor().equals(usuario.getEmail())) { - throw new PermissionDeniedException("A questão é de propriedade de outro usuário"); - } - if (!questao.getEstado().equals(EstadoQuestao.RASCUNHO)) { - throw new PermissionDeniedException("Apenas questões rascunho podem ser removidas"); - } - questao = questaoService.delete(id); - return new ResponseEntity(convert(questao, usuario, false), HttpStatus.OK); - } - - @ApiOperation("Permite atualizar uma questão do sistema. Requer que o corpo do request contenha um objeto com os atributos de uma questão subjetiva.\r\n" - + "") - @ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = Questao.class) }) - @RequestMapping(value = "/questao/{id}", method = RequestMethod.PUT) - public ResponseEntity update(@PathVariable("id") String id, @RequestAttribute(name="usuario") Usuario usuario, @RequestBody QuestaoInput questao) throws IOException { - Questao q = QuestaoIO.convert(questao, usuario.getEmail()); - q.setQtdAvaliacoes(1); - Questao oldQuestion = questaoService.getById(id); - if (!oldQuestion.getEstado().equals(EstadoQuestao.RASCUNHO)) { - throw new PermissionDeniedException("Uma questão definitiva não pode ser mais alterada"); - } - Questao updatedQuestao = questaoService.update(q, id); - - - return new ResponseEntity(convert(updatedQuestao, usuario, false), HttpStatus.OK); - } - - - @ApiOperation("Retorna a(s) competência(s) para o enunciado.\r\n" - + "") - @ApiResponses(value = { @ApiResponse(code = 200, message = "OK") }) - @RequestMapping(value = "/competencias", method = RequestMethod.POST) - public Set getSetCompetencias(@RequestBody String enunciado) throws IOException { - return questaoService.getSetCompetencias(enunciado); - } - - @ApiOperation("Fornece uma questão pendente de avaliação para o usuário.\r\n" + "") - @ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = Questao.class) }) - @RequestMapping(value = "/questao/pendente/", method = RequestMethod.GET) - public QuestaoOutput getPendente(@RequestAttribute(name="usuario") Usuario usuario) throws IOException { - return convert(questaoService.getPendente(usuario), usuario, false); - } - - @ApiOperation("Fornece uma questão pendente de aprovação para publicação para o usuário.\r\n" + "") - @ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = Questao.class) }) - @RequestMapping(value = "/questao/avaliada/", method = RequestMethod.GET) - public QuestaoOutput getAvaliada(@RequestAttribute(name="usuario") Usuario usuario) throws IOException { - return convert(questaoService.getAvaliada(), usuario, true); - } - - @ApiOperation("Permite enviar questão para avaliação.") - @ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = Questao.class) }) - @RequestMapping(value = "/questao/publish/{id}", method = RequestMethod.PUT) - public ResponseEntity publish(@RequestAttribute(name="usuario") Usuario usuario, @PathVariable("id") String id) throws IOException { - Questao questao = questaoService.getById(id); - if (!questao.getAutor().equals(usuario.getEmail())) { - throw new PermissionDeniedException("A questão é de propriedade de outro usuário"); - } - if (!questao.getEstado().equals(EstadoQuestao.RASCUNHO)) { - throw new PermissionDeniedException("Apenas questões rascunho podem ser publicadas"); - } - questao.setEstado(EstadoQuestao.PEND_AVALIACAO); - questao = questaoService.update(questao, id); - return new ResponseEntity(convert(questao, usuario, false), HttpStatus.OK); - } - - @ApiOperation("Aprovar questão já avaliada.") - @ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = Questao.class) }) - @RequestMapping(value = "/questao/aprove/{id}", method = RequestMethod.PUT) + @Autowired + private QuestaoService questaoService; + + @Autowired + private AvaliacaoController avaliacaoController; + + @Autowired + private ConteudoService conteudoService; + + @Autowired + private QuestaoIO questaoIO; + + private QuestaoOutput convertToDto(Questao questao, Usuario usuario, boolean forceAvaliacoes) { + return questaoIO.toDto(questao, usuario, forceAvaliacoes); + } + + @PostMapping("/questao") + @Operation(summary = "Permite registrar uma nova questão no sistema.", responses = { + @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = QuestaoOutput.class))) + }) + public QuestaoOutput saveQuestao(@RequestAttribute(name = "usuario") Usuario usuario, + @RequestBody QuestaoInput questaoInput) throws IOException { + Questao questaoSalva = questaoService.save(QuestaoIO.toEntity(questaoInput, usuario.getEmail())); + AvaliacaoInput avaliacaoInput = new AvaliacaoInput( + questaoInput.getObsAvaliacao(), "", questaoSalva.getId(), + questaoInput.getCompetenciasAvaliacao(), questaoInput.getInfoCompetenciasAvaliacao(), + questaoInput.getConfiancaAvaliacao(), AvaliacaoPublicacao.PRONTA); + avaliacaoController.save(usuario, avaliacaoInput); + return convertToDto(questaoSalva, usuario, false); + } + + @PostMapping("/conteudo") + @Operation(summary = "Permite salvar um novo conteúdo no sistema.", responses = { + @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = Conteudo.class))) + }) + public ResponseEntity saveConteudo(@RequestBody String conteudo) { + Conteudo conteudoSalvo = conteudoService.save(new Conteudo(conteudo)); + return ResponseEntity.ok(conteudoSalvo); + } + + @GetMapping("/conteudo") + @Operation(summary = "Recupera todos os conteúdos do sistema.", responses = { + @ApiResponse(responseCode = "200", description = "OK", content = @Content(mediaType = "application/json", schema = @Schema(implementation = String.class))) + }) + public ResponseEntity> getAllConteudo() { + List conteudos = conteudoService.getAll().stream() + .map(Conteudo::getNome) + .filter(nome -> !nome.equals("Outros")) + .collect(Collectors.toList()); + conteudos.add("Outros"); + return ResponseEntity.ok(conteudos); + } + + @DeleteMapping("/questao/{id}") + @Operation(summary = "Permite apagar uma questão do sistema.", responses = { + @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = QuestaoOutput.class))) + }) + public ResponseEntity deleteQuestao(@RequestAttribute(name = "usuario") Usuario usuario, + @PathVariable("id") String id) { + Questao questao = questaoService.getById(id); + validateUserAuthorization(usuario, questao); + validateQuestaoState(questao, EstadoQuestao.RASCUNHO, "Apenas questões rascunho podem ser removidas"); + + Questao deletedQuestao = questaoService.delete(id); + return ResponseEntity.ok(convertToDto(deletedQuestao, usuario, false)); + } + + @PutMapping("/questao/{id}") + @Operation(summary = "Permite atualizar uma questão do sistema.", responses = { + @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = QuestaoOutput.class))) + }) + public ResponseEntity updateQuestao(@PathVariable("id") String id, + @RequestAttribute(name = "usuario") Usuario usuario, @RequestBody QuestaoInput questaoInput) + throws IOException { + Questao oldQuestao = questaoService.getById(id); + validateQuestaoState(oldQuestao, EstadoQuestao.RASCUNHO, "Uma questão definitiva não pode ser mais alterada"); + + Questao updatedQuestao = questaoService.update(QuestaoIO.toEntity(questaoInput, usuario.getEmail()), id); + return ResponseEntity.ok(convertToDto(updatedQuestao, usuario, false)); + } + + @PostMapping("/competencias") + @Operation(summary = "Retorna a(s) competência(s) para o enunciado.", responses = { + @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = CompetenciaType.class))) + }) + public Set getCompetencias(@RequestBody String enunciado) throws IOException { + return questaoService.getSetCompetencias(enunciado); + } + + @GetMapping("/questao/pendente") + @Operation(summary = "Fornece uma questão pendente de avaliação para o usuário.", responses = { + @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = Questao.class))) + }) + public QuestaoOutput getPendente(@RequestAttribute(name = "usuario") Usuario usuario) throws IOException { + return convertToDto(questaoService.getPendente(usuario), usuario, false); + } + + @GetMapping("/questao/avaliada") + @Operation(summary = "Fornece uma questão pendente de aprovação para publicação para o usuário.", responses = { + @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = QuestaoOutput.class))) + }) + public QuestaoOutput getAvaliada(@RequestAttribute(name = "usuario") Usuario usuario) { + return convertToDto(questaoService.getAvaliada(), usuario, true); + } + + @PutMapping("/questao/publish/{id}") + @Operation(summary = "Permite enviar questão para avaliação.", responses = { + @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = QuestaoOutput.class))) + }) + public ResponseEntity publishQuestao(@RequestAttribute(name = "usuario") Usuario usuario, + @PathVariable("id") String id) throws IOException { + Questao questao = questaoService.getById(id); + validateUserAuthorization(usuario, questao); + validateQuestaoState(questao, EstadoQuestao.RASCUNHO, "Apenas questões rascunho podem ser publicadas"); + + questao.setEstado(EstadoQuestao.PEND_AVALIACAO); + Questao publishedQuestao = questaoService.update(questao, id); + return ResponseEntity.ok(convertToDto(publishedQuestao, usuario, false)); + } + + @PutMapping("/questao/aprove/{id}") + @Operation(summary = "Aprova uma questão já avaliada.", responses = { + @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = QuestaoOutput.class))) + }) public ResponseEntity aprovarQuestao(@RequestAttribute(name="usuario") Usuario usuario, @PathVariable("id") String id, @RequestBody QuestaoInput novaQuestaoInput) throws IOException { Questao questao = questaoService.getById(id); - Questao novaQuestao = QuestaoIO.convert(novaQuestaoInput, questao.getAutor()); + Questao novaQuestao = QuestaoIO.toEntity(novaQuestaoInput, questao.getAutor()); if (!usuario.getPermissoes().contains(PermissaoType.JUDGE)) { throw new PermissionDeniedException("Apenas um usuário com permissão de juiz pode aprovar/reprovar uma questão"); @@ -188,12 +171,13 @@ public ResponseEntity aprovarQuestao(@RequestAttribute(name="usua } novaQuestao.setEstado(EstadoQuestao.PUBLICADA); questao = questaoService.update(novaQuestao, id); - return new ResponseEntity(convert(questao, usuario, false), HttpStatus.OK); + return ResponseEntity.ok(convertToDto(questao, usuario, false)); } - @ApiOperation("Rejeitar questão já avaliada.") - @ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = Questao.class) }) - @RequestMapping(value = "/questao/reject/{id}", method = RequestMethod.PUT) + @PutMapping("/questao/reject/{id}") + @Operation(summary = "Permite rejeitar questão já avaliada.", responses = { + @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = QuestaoOutput.class))) + }) public ResponseEntity rejeitarQuestao(@RequestAttribute(name="usuario") Usuario usuario, @PathVariable("id") String id) throws IOException { Questao questao = questaoService.getById(id); if (!usuario.getPermissoes().contains(PermissaoType.JUDGE)) { @@ -204,16 +188,29 @@ public ResponseEntity rejeitarQuestao(@RequestAttribute(name="usu } questao.setEstado(EstadoQuestao.REJEITADA); questao = questaoService.update(questao, id); - return new ResponseEntity(convert(questao, usuario, false), HttpStatus.OK); + return ResponseEntity.ok(convertToDto(questao, usuario, false)); } - @ApiOperation("Atualizar competenciaClassificador questão já avaliada.") - @ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = Questao.class) }) - @RequestMapping(value = "/updateClassificador", method = RequestMethod.GET) + @GetMapping("/updateClassificador") + @Operation(summary = "Atualiza competenciaClassificador questão já avaliada", responses = { + @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = QuestaoOutput.class))) + }) public ResponseEntity updateCompetencias(@RequestAttribute(name="usuario") Usuario usuario) throws IOException { if (!usuario.getPermissoes().contains(PermissaoType.JUDGE)) { throw new PermissionDeniedException("Apenas um usuário com permissão de juiz pode atualizar a classificação automática das questões"); } - return new ResponseEntity(questaoService.updateClassificador(), HttpStatus.OK); + return ResponseEntity.ok(questaoService.updateClassificador()); } + + private void validateUserAuthorization(Usuario usuario, Questao questao) { + if (!questao.getAutor().equals(usuario.getEmail())) { + throw new PermissionDeniedException("A questão é de propriedade de outro usuário"); + } + } + + private void validateQuestaoState(Questao questao, EstadoQuestao estado, String errorMessage) { + if (!questao.getEstado().equals(estado)) { + throw new IllegalStateException(errorMessage); + } + } } diff --git a/backend/src/main/java/springboot/controller/QuestionSearchController.java b/backend/src/main/java/springboot/controller/QuestionSearchController.java index 7adb83ac..37b5a7c8 100644 --- a/backend/src/main/java/springboot/controller/QuestionSearchController.java +++ b/backend/src/main/java/springboot/controller/QuestionSearchController.java @@ -1,107 +1,125 @@ package springboot.controller; import java.util.HashSet; -import java.util.List; import java.util.Set; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.http.MediaType; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; import springboot.dto.IO.QuestaoIO; import springboot.dto.output.QuestaoOutput; import springboot.enums.EstadoQuestao; -import springboot.model.Conteudo; import springboot.model.Questao; import springboot.model.Usuario; -import springboot.service.AvaliacaoService; -import springboot.service.ConteudoService; import springboot.service.QuestaoService; -import springboot.service.UsuarioService; -@Controller @RestController -@RequestMapping(value = "/api") -@CrossOrigin(origins = "+") -@Api(value = "QuestaoSearchControllerAPI", produces = MediaType.APPLICATION_JSON_VALUE) +@RequestMapping(value = "/api/questao") +@CrossOrigin(origins = "*") public class QuestionSearchController { - - @Autowired - QuestaoService questaoService; - @Autowired - AvaliacaoService avaliacaoService; + @Autowired + private QuestaoIO questaoIO; - @Autowired - UsuarioService usuarioService; + @Autowired + private QuestaoService questaoService; + + private QuestaoOutput convertToOutput(Questao questao, Usuario usuario) { + return questaoIO.toDto(questao, usuario, false); + } - @Autowired - ConteudoService conteudoService; + @Operation(summary = "Fornece um array de objetos do tipo questão registrados.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "OK", content = {@io.swagger.v3.oas.annotations.media.Content(mediaType = MediaType.APPLICATION_JSON_VALUE)}) + }) + @GetMapping("/{page}/{size}") + public Page getAll( + @RequestAttribute(name="usuario") Usuario usuario, + @PathVariable int page, + @PathVariable int size + ) { + return questaoService.getAll(page, size) + .map(q -> convertToOutput(q, usuario)); + } - private QuestaoOutput convert(Questao questao, Usuario usuario) { - return QuestaoIO.convert(questao, usuario, usuarioService, avaliacaoService, questaoService, false); - } - - - @ApiOperation("Fornece um array de objetos do tipo questão registrados.\r\n" + "") - @ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = Questao.class) }) - @RequestMapping(value = "/questao/{page}/{size}", method = RequestMethod.GET) - public Page getAll(@RequestAttribute(name="usuario") Usuario usuario, @PathVariable("page") int page, @PathVariable("size") int size) { - return questaoService.getAll(page,size).map(q -> this.convert(q, usuario)); - } - - @ApiOperation("Fornece os dados de uma questão em particular. O objeto contém: tipo, enunciado, fonte, autor, imagem, competencias e espelho.\r\n" - + "") - @ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = Questao.class) }) - @RequestMapping(value = "/questao/{id}", method = RequestMethod.GET) - public QuestaoOutput getById(@RequestAttribute(name="usuario") Usuario usuario, @PathVariable("id") String id) { - return convert(questaoService.getById(id), usuario); - } - - - @ApiOperation("Fornece um array de questões que fazem o match com o enunciado, competências (cada uma entre aspas), " - + "autor, fonte e tipo\r\n" + "") - @ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = Questao.class) }) - @RequestMapping(value = "/questao/search/{enunciado}/{competencias}/{autor}/{fonte}/{tipo}/{conteudo}/{page}/{size}", method = RequestMethod.GET) - public Page getByEnunciadoCompetenciasAutorFonteTipo(@RequestAttribute(name="usuario") Usuario usuario, - @PathVariable("enunciado") String enunciado, - @PathVariable("competencias") HashSet competencias,@PathVariable("autor") String autor, - @PathVariable("fonte") String fonte, @PathVariable("tipo") String tipo, @PathVariable("conteudo") HashSet conteudo, - @PathVariable("page") int page,@PathVariable("size") int size) { - System.out.println(competencias); - Set estados = new HashSet<>(); - Set newConteudo = new HashSet<>(); - for(String conteudoItem : conteudo) { - if (!conteudoItem.equals("")) - newConteudo.add(conteudoItem); - } - estados.add(EstadoQuestao.PUBLICADA); - return questaoService.getByEnunciadoCompetenciasAutorFonteTipo(enunciado, competencias, autor, "", fonte, tipo,newConteudo, estados, page,size).map(q -> this.convert(q, usuario)); - } - - @ApiOperation("Fornece um array de questões que fazem o match com o enunciado, competências (cada uma entre aspas), " - + "autor, fonte e tipo\r\n" + "") - @ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = Questao.class) }) - @RequestMapping(value = "/questao/searchMy/{enunciado}/{competencias}/{estados}/{fonte}/{tipo}/{conteudo}/{page}/{size}", method = RequestMethod.GET) - public Page getMyQuestionsByEnunciadoCompetenciasAutorFonteTipo(@RequestAttribute(name="usuario") Usuario usuario, @PathVariable("enunciado") String enunciado, - @PathVariable("competencias") HashSet competencias, @PathVariable("estados") HashSet estados, - @PathVariable("fonte") String fonte, @PathVariable("tipo") String tipo, @PathVariable("conteudo") HashSet conteudo, - @PathVariable("page") int page, @PathVariable("size") int size) { - Set newConteudo = new HashSet<>(); - for(String conteudoItem : conteudo) { - if (!conteudoItem.equals("")) - newConteudo.add(conteudoItem); - } - System.out.println(competencias); - return questaoService.getByEnunciadoCompetenciasAutorFonteTipo(enunciado, competencias, "", usuario.getEmail(), fonte, tipo,newConteudo, estados, page,size).map(q -> this.convert(q, usuario)); - } + @Operation(summary = "Fornece os dados de uma questão em particular.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "OK", content = {@io.swagger.v3.oas.annotations.media.Content(mediaType = MediaType.APPLICATION_JSON_VALUE)}) + }) + @GetMapping("/{id}") + public QuestaoOutput getById( + @RequestAttribute(name="usuario") Usuario usuario, + @PathVariable String id + ) { + return convertToOutput(questaoService.getById(id), usuario); + } + @Operation(summary = "Busca questões com base em diversos critérios.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "OK", content = {@io.swagger.v3.oas.annotations.media.Content(mediaType = MediaType.APPLICATION_JSON_VALUE)}) + }) + @GetMapping("/search") + public Page search( + @RequestAttribute(name="usuario") Usuario usuario, + @RequestParam(required = false) String enunciado, + @RequestParam(required = false) Set competencias, + @RequestParam(required = false) String autor, + @RequestParam(required = false) String fonte, + @RequestParam(required = false) String tipo, + @RequestParam(required = false) Set conteudo, + @RequestParam int page, + @RequestParam int size + ) { + Set estados = new HashSet<>(); + estados.add(EstadoQuestao.PUBLICADA); + Set newConteudo = cleanSet(conteudo); + return questaoService.getByEnunciadoCompetenciasAutorFonteTipo( + enunciado, (HashSet) competencias, autor, "", fonte, tipo, newConteudo, estados, page, size + ).map(q -> convertToOutput(q, usuario)); + } + @Operation(summary = "Busca questões do usuário logado com base em diversos critérios.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "OK", content = {@io.swagger.v3.oas.annotations.media.Content(mediaType = MediaType.APPLICATION_JSON_VALUE)}) + }) + @GetMapping("/searchMy") + public Page searchMyQuestions( + @RequestAttribute(name="usuario") Usuario usuario, + @RequestParam(required = false) String enunciado, + @RequestParam(required = false) Set competencias, + @RequestParam(required = false) Set estados, + @RequestParam(required = false) String fonte, + @RequestParam(required = false) String tipo, + @RequestParam(required = false) Set conteudo, + @RequestParam int page, + @RequestParam int size + ) { + Set newConteudo = cleanSet(conteudo); + return questaoService.getByEnunciadoCompetenciasAutorFonteTipo( + enunciado, (HashSet) competencias, "", usuario.getEmail(), fonte, tipo, newConteudo, estados, page, size + ).map(q -> convertToOutput(q, usuario)); + } + private Set cleanSet(Set originalSet) { + Set cleanedSet = new HashSet<>(); + if (originalSet != null) { + for (String item : originalSet) { + if (item != null && !item.isEmpty()) { + cleanedSet.add(item); + } + } + } + return cleanedSet; + } } diff --git a/backend/src/main/java/springboot/controller/UsuarioController.java b/backend/src/main/java/springboot/controller/UsuarioController.java index 85e6ca50..ad47ecce 100644 --- a/backend/src/main/java/springboot/controller/UsuarioController.java +++ b/backend/src/main/java/springboot/controller/UsuarioController.java @@ -1,75 +1,66 @@ package springboot.controller; -import java.util.List; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.*; - -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponses; -import io.swagger.annotations.ApiResponse; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestAttribute; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; -import org.springframework.http.MediaType; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; import springboot.model.Usuario; import springboot.service.UsuarioService; -@Controller @RestController @RequestMapping(value = "/api") -@CrossOrigin(origins = "+") -@Api(value = "UsuariosControllerAPI", produces = MediaType.APPLICATION_JSON_VALUE) +@CrossOrigin(origins = "*") public class UsuarioController { - @Autowired - UsuarioService usuarioService; - - /* - @ApiOperation("Permite apagar um usuário do sistema.") - @ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = Usuario.class) }) - @RequestMapping(value = "/usuario/{email}", method = RequestMethod.DELETE) - public ResponseEntity delete(@PathVariable("email") String email) { - Usuario usuario = usuarioService.delete(email); - return new ResponseEntity(usuario, HttpStatus.OK); - }*/ - - @ApiOperation("Permite atualizar um usuário do sistema. Requer que o corpo do request contenha um objeto com os atributos de um usuário.\r\n") - @ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = Usuario.class) }) - @RequestMapping(value = "/usuario/", method = RequestMethod.PUT) - public ResponseEntity update(@RequestAttribute(name="usuario") Usuario oldUsuario, @RequestBody Usuario novoUsuario) { - Usuario updatedUsuario = usuarioService.update(new Usuario(oldUsuario.getNome(), novoUsuario.getIdade(), novoUsuario.getNomeInstituicao(), novoUsuario.getCargo(), novoUsuario.getCidade(), oldUsuario.getEmail(),true), oldUsuario.getEmail()); - return new ResponseEntity(updatedUsuario, HttpStatus.OK); - } - - /* - @ApiOperation("Fornece um array de objetos do tipo usuario registrados.") - @ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = Usuario.class) }) - @RequestMapping(value = "/usuario", method = RequestMethod.GET) - public List getAll() { - return usuarioService.getAll(); - } - - - @ApiOperation("Recupera um usuario com específico email.") - @ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = Usuario.class) }) - @RequestMapping(value = "/usuario/{email}", method = RequestMethod.GET) - public Usuario getByEmail(@PathVariable("email") String email) { - return usuarioService.getById(email); - }*/ + @Autowired + private UsuarioService usuarioService; - @ApiOperation("Recupera informaçoes do usuario atual.") - @ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = Usuario.class) }) - @RequestMapping(value = "/usuario/", method = RequestMethod.GET) - public Usuario getActualUser(@RequestAttribute(name="usuario") Usuario usuario) { - return usuario; - } - /* - * @RequestMapping(value = "/usuario/search/{nome}", method = RequestMethod.GET) - * public Usuario searchByNome(@PathVariable("nome") String nome) { return - * usuarioService.pesquisarPorNome(nome); } - */ + /** + * Atualiza as informações do usuário logado. + * + * @param oldUsuario O usuário logado atualmente (preenchido automaticamente + * pelo Spring). + * @param novoUsuario As novas informações do usuário, exceto o email. + * @return O usuário atualizado. + */ + @Operation(summary = "Atualiza as informações do usuário logado. Requer que o corpo do request contenha um objeto com os atributos do usuário, exceto o e-mail.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "OK", content = {@io.swagger.v3.oas.annotations.media.Content(mediaType = MediaType.APPLICATION_JSON_VALUE)}), + }) + @PutMapping(value = "/usuario") + public ResponseEntity update(@RequestAttribute(name = "usuario") Usuario oldUsuario, + @RequestBody Usuario novoUsuario) { + Usuario updatedUsuario = usuarioService.update( + new Usuario(oldUsuario.getNome(), novoUsuario.getIdade(), novoUsuario.getNomeInstituicao(), + novoUsuario.getCargo(), novoUsuario.getCidade(), oldUsuario.getEmail(), true), + oldUsuario.getEmail()); + return new ResponseEntity<>(updatedUsuario, HttpStatus.OK); + } + /** + * Recupera as informações do usuário atual logado. + * + * @param usuario O usuário logado atualmente (preenchido automaticamente pelo + * Spring). + * @return O usuário logado. + */ + @Operation(summary = "Recupera as informações do usuário atual logado.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "OK", content = {@io.swagger.v3.oas.annotations.media.Content(mediaType = MediaType.APPLICATION_JSON_VALUE)}) + }) + @GetMapping(value = "/usuario") + public ResponseEntity getActualUser(@RequestAttribute(name = "usuario") Usuario usuario) { + return new ResponseEntity<>(usuario, HttpStatus.OK); + } } From 0bb3fd7762bce54e4499ebbb0dad10d95d1ea992 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Vitor?= Date: Tue, 17 Sep 2024 02:38:01 -0300 Subject: [PATCH 05/18] refactor IO/DTOs files --- .../springboot/dto/IO/ListaQuestoesIO.java | 64 ++++++-- .../java/springboot/dto/IO/QuestaoIO.java | 141 ++++++++++++----- .../springboot/dto/input/AvaliacaoInput.java | 110 +++++++------ .../dto/input/ListaQuestoesInput.java | 53 +++++-- .../springboot/dto/input/QuestaoInput.java | 146 +++++++++--------- .../springboot/dto/input/UsuarioInput.java | 57 ++++--- .../springboot/dto/output/CursoOutput.java | 5 +- .../dto/output/ListaQuestoesOutput.java | 3 - .../dto/output/ModuloCursoOutput.java | 2 - 9 files changed, 341 insertions(+), 240 deletions(-) diff --git a/backend/src/main/java/springboot/dto/IO/ListaQuestoesIO.java b/backend/src/main/java/springboot/dto/IO/ListaQuestoesIO.java index 79559200..e4825385 100644 --- a/backend/src/main/java/springboot/dto/IO/ListaQuestoesIO.java +++ b/backend/src/main/java/springboot/dto/IO/ListaQuestoesIO.java @@ -1,32 +1,62 @@ package springboot.dto.IO; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + import springboot.dto.input.ListaQuestoesInput; -import springboot.dto.input.QuestaoInput; import springboot.dto.output.ListaQuestoesOutput; import springboot.model.ListaQuestoes; import springboot.model.Questao; import springboot.model.Usuario; import springboot.service.QuestaoService; - -import java.util.ArrayList; -import java.util.List; - +/** + * Classe responsável pela conversão entre DTOs e entidades do modelo + * ListaQuestoes. + */ +@Component public class ListaQuestoesIO { + private final QuestaoService questaoService; + + /** + * Construtor para injeção de dependências. + * + * @param questaoService Serviço de questões para operações de busca. + */ + @Autowired + public ListaQuestoesIO(QuestaoService questaoService) { + this.questaoService = questaoService; + } - public static ListaQuestoes convert(ListaQuestoesInput listaQuestoes, Usuario usuario, QuestaoService questaoService) { - List questoes = new ArrayList<>(); - for (String questao: listaQuestoes.getQuestoes()) { - questoes.add(questaoService.getById(questao).getId()); - } - return new ListaQuestoes(listaQuestoes.getNomeLista(), usuario.getEmail(), questoes); + /** + * Converte um DTO de entrada para uma entidade de modelo. + * + * @param listaQuestoesInput Objeto DTO de entrada. + * @param usuario Objeto do usuário associado. + * @return ListaQuestoes Entidade de modelo. + */ + public ListaQuestoes toEntity(ListaQuestoesInput listaQuestoesInput, Usuario usuario) { + List questoes = listaQuestoesInput.getQuestoes().stream() + .map(questaoId -> questaoService.getById(questaoId).getId()) + .collect(Collectors.toList()); + return new ListaQuestoes(listaQuestoesInput.getNomeLista(), usuario.getEmail(), questoes); } - public static ListaQuestoesOutput convert(ListaQuestoes listaQuestoes, String autor, QuestaoService questaoService) { - List questoes = new ArrayList<>(); - for (String questao: listaQuestoes.getQuestoes()) { - questoes.add(questaoService.getById(questao)); - } - return new ListaQuestoesOutput(listaQuestoes.getId(), listaQuestoes.getNomeLista(), autor, questoes); + /** + * Converte uma entidade de modelo para um DTO de saída. + * + * @param listaQuestoes Entidade de modelo. + * @param autor Autor da lista de questões. + * @return ListaQuestoesOutput DTO de saída. + */ + public ListaQuestoesOutput toDto(ListaQuestoes listaQuestoes, String autor) { + List questoes = listaQuestoes.getQuestoes().stream() + .map(questaoId -> Optional.ofNullable(questaoService.getById(questaoId)) + .orElseThrow(() -> new IllegalArgumentException("Questão não encontrada: ".concat(questaoId)))) + .collect(Collectors.toList()); + return new ListaQuestoesOutput(listaQuestoes.getId(), listaQuestoes.getNomeLista(), autor, questoes); } } diff --git a/backend/src/main/java/springboot/dto/IO/QuestaoIO.java b/backend/src/main/java/springboot/dto/IO/QuestaoIO.java index a9004ace..845f5b5d 100644 --- a/backend/src/main/java/springboot/dto/IO/QuestaoIO.java +++ b/backend/src/main/java/springboot/dto/IO/QuestaoIO.java @@ -1,67 +1,128 @@ package springboot.dto.IO; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.Set; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + import springboot.dto.input.QuestaoInput; import springboot.dto.output.QuestaoOutput; import springboot.enums.AvaliacaoPublicacao; import springboot.enums.CompetenciaType; import springboot.enums.EstadoQuestao; import springboot.model.Avaliacao; -import springboot.model.Conteudo; import springboot.model.Questao; import springboot.model.Usuario; import springboot.service.AvaliacaoService; -import springboot.service.QuestaoService; import springboot.service.UsuarioService; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - +/** + * Classe responsável pela conversão entre DTOs e entidades de Questão. + */ +@Component public class QuestaoIO { + private final UsuarioService usuarioService; + private final AvaliacaoService avaliacaoService; + + @Autowired + public QuestaoIO(UsuarioService usuarioService, AvaliacaoService avaliacaoService) { + this.usuarioService = usuarioService; + this.avaliacaoService = avaliacaoService; + } - public static Questao convert(QuestaoInput questao, String autor) { - return new Questao(questao.getTipo(), questao.getConteudo(), questao.getEnunciado(), questao.getFonte(), autor, questao.getEspelho(), questao.getAlternativas(), questao.getCompetencias()); + /** + * Converte um DTO de entrada para uma entidade de Questão. + * + * @param questaoInput Objeto DTO de entrada. + * @param autor E-mail do autor da questão. + * @return Questao Entidade de modelo. + */ + public static Questao toEntity(QuestaoInput questaoInput, String autor) { + return new Questao( + questaoInput.getTipo(), + questaoInput.getConteudo(), + questaoInput.getEnunciado(), + questaoInput.getFonte(), + autor, + questaoInput.getEspelho(), + questaoInput.getAlternativas(), + questaoInput.getCompetencias()); } - public static QuestaoOutput convert(Questao questao, Usuario usuarioAtual, UsuarioService usuarioService, AvaliacaoService avaliacaoService, QuestaoService questaoService, boolean forceAvaliacoes) { + /** + * Converte uma entidade de Questão para um DTO de saída. + * + * @param questao Entidade de Questão. + * @param usuarioAtual Usuário atualmente logado. + * @param forceAvaliacoes Flag para forçar a inclusão de todas as avaliações. + * @return QuestaoOutput DTO de saída. + */ + public QuestaoOutput toDto(Questao questao, Usuario usuarioAtual, boolean forceAvaliacoes) { List sugestoes = new ArrayList<>(); String originalEnunciado = null; - List > competenciasAvaliacoes = new ArrayList<>(); + List> competenciasAvaliacoes = new ArrayList<>(); List avalPublicacoes = new ArrayList<>(); - if ((usuarioAtual.getEmail().equals(questao.getAutor()) && questao.getEstado().equals(EstadoQuestao.REJEITADA)) || forceAvaliacoes) { - List avaliacoes = avaliacaoService.getAllByQuestao(questao.getId()).subList(1, 3); - for (Avaliacao aval : avaliacoes) { - avalPublicacoes.add(aval.getAvaliacaoPublicacao()); - String tmp = aval.getObservacaoQuestao().trim().equals("") ? "Sem sugestões" : aval.getObservacaoQuestao(); - if (aval.getAvaliacaoPublicacao().equals(AvaliacaoPublicacao.PRONTA)) { - tmp += " (Pronta para publicação)"; - } else if (aval.getAvaliacaoPublicacao().equals(AvaliacaoPublicacao.PEQUENAS_ALTERACOES)) { - tmp += " (Necessita de pequenas alterações)"; - } else if (aval.getAvaliacaoPublicacao().equals(AvaliacaoPublicacao.MUITAS_ALTERACOES)) { - tmp += " (Necessita de muitas alterações)"; - } else { - tmp += " (Fora de contexto)"; - } - sugestoes.add(tmp); - } - } - if ((usuarioAtual.getEmail().equals(questao.getAutor()) && (questao.getEstado().equals(EstadoQuestao.REJEITADA) || questao.getEstado().equals(EstadoQuestao.PUBLICADA))) || forceAvaliacoes) { - competenciasAvaliacoes.add(questao.getCompetenciasClassificador()); - ListavaliacoesQuestao = avaliacaoService.getAllByQuestao(questao.getId()); - if (avaliacoesQuestao.size() > 3) { - avaliacoesQuestao = avaliacoesQuestao.subList(0, 3); - } - for (Avaliacao av : avaliacoesQuestao) { - competenciasAvaliacoes.add(av.getCompetencias()); - } - } + boolean isAutorOuForce = usuarioAtual.getEmail().equals(questao.getAutor()) && + (questao.getEstado() == EstadoQuestao.REJEITADA || questao.getEstado() == EstadoQuestao.PUBLICADA) || + forceAvaliacoes; + + if (isAutorOuForce) + processarAvaliacoes(questao, sugestoes, avalPublicacoes, competenciasAvaliacoes); - if (usuarioAtual.getEmail().equals(questao.getAutor()) && questao.getEstado() == EstadoQuestao.PUBLICADA && !questao.getEnunciado().equals(questao.getOriginalEnunciado())) { + if (usuarioAtual.getEmail().equals(questao.getAutor()) && + questao.getEstado() == EstadoQuestao.PUBLICADA && + !questao.getEnunciado().equals(questao.getOriginalEnunciado())) { originalEnunciado = questao.getOriginalEnunciado(); } - return new QuestaoOutput(questao.getId(), questao.getTipo(), questao.getEnunciado(), originalEnunciado, usuarioService.getById(questao.getAutor()).getNome(), questao.getAutor(), questao.getCompetencias(), competenciasAvaliacoes, questao.getFonte(), questao.getEspelho(), questao.getConteudo(), questao.getAlternativas(), sugestoes, avalPublicacoes, questao.getEstado()); + + String autorNome = Optional.ofNullable(usuarioService.getById(questao.getAutor())) + .map(Usuario::getNome) + .orElse("Autor Desconhecido"); + + return new QuestaoOutput( + questao.getId(), + questao.getTipo(), + questao.getEnunciado(), + originalEnunciado, + autorNome, + questao.getAutor(), + questao.getCompetencias(), + competenciasAvaliacoes, + questao.getFonte(), + questao.getEspelho(), + questao.getConteudo(), + questao.getAlternativas(), + sugestoes, + avalPublicacoes, + questao.getEstado()); + } + + private void processarAvaliacoes(Questao questao, List sugestoes, List avalPublicacoes, + List> competenciasAvaliacoes) { + List avaliacoes = avaliacaoService.getAllByQuestao(questao.getId()); + + avaliacoes.stream().limit(3).forEach(aval -> { + avalPublicacoes.add(aval.getAvaliacaoPublicacao()); + String sugestao = obterSugestao(aval); + sugestoes.add(sugestao); + competenciasAvaliacoes.add(aval.getCompetencias()); + }); + competenciasAvaliacoes.add(questao.getCompetenciasClassificador()); + } + + private String obterSugestao(Avaliacao avaliacao) { + String sugestaoBase = avaliacao.getObservacaoQuestao().trim().isEmpty() ? "Sem sugestões" + : avaliacao.getObservacaoQuestao(); + return switch (avaliacao.getAvaliacaoPublicacao()) { + case PRONTA -> sugestaoBase.concat(" (Pronta para publicação)"); + case PEQUENAS_ALTERACOES -> sugestaoBase.concat(" (Necessita de pequenas alterações)"); + case MUITAS_ALTERACOES -> sugestaoBase.concat(" (Necessita de muitas alterações)"); + default -> sugestaoBase.concat(" (Fora de contexto)"); + }; } } diff --git a/backend/src/main/java/springboot/dto/input/AvaliacaoInput.java b/backend/src/main/java/springboot/dto/input/AvaliacaoInput.java index 0c58314f..1b267047 100644 --- a/backend/src/main/java/springboot/dto/input/AvaliacaoInput.java +++ b/backend/src/main/java/springboot/dto/input/AvaliacaoInput.java @@ -1,90 +1,88 @@ package springboot.dto.input; -import springboot.enums.AvaliacaoPublicacao; -import springboot.enums.CompetenciaType; - +import java.util.Arrays; import java.util.List; -import java.util.Map; +import java.util.Optional; import java.util.Set; -public class AvaliacaoInput { - private String observacaoAvaliacao; - - private String observacaoQuestao; - - private String questao; - - private Set competencias; - - private List infoCompetencias; - - private Integer confianca; - - private AvaliacaoPublicacao avaliacaoPublicacao; +import springboot.enums.AvaliacaoPublicacao; +import springboot.enums.CompetenciaType; - public AvaliacaoInput(String observacaoAvaliacao, String observacaoQuestao, String questao, Set competencias, List infoCompetencias, Integer confianca, AvaliacaoPublicacao avaliacaoPublicacao) { - this.observacaoAvaliacao = observacaoAvaliacao; - this.observacaoQuestao = observacaoQuestao; - this.questao = questao; - this.competencias = competencias; - this.infoCompetencias = infoCompetencias; - this.confianca = confianca; - this.avaliacaoPublicacao = avaliacaoPublicacao; +/** + * DTO para entrada de dados de Avaliação. + */ +public final class AvaliacaoInput { + + private final String observacaoAvaliacao; + private final String observacaoQuestao; + private final String questaoId; + private final Set competencias; + private final List infoCompetencias; + private final Integer confianca; + private final AvaliacaoPublicacao avaliacaoPublicacao; + + /** + * Construtor para inicializar todos os campos da Avaliação. + * + * @param observacaoAvaliacao Observação geral sobre a avaliação. + * @param observacaoQuestao Observação específica sobre a questão. + * @param questaoId Identificador da questão a ser avaliada. + * @param competencias Competências aplicáveis à avaliação. + * @param infoCompetencias Informações adicionais sobre as competências. + * @param confianca Nível de confiança na avaliação (deve estar entre + * 0 e 100). + * @param avaliacaoPublicacao Status de publicação da avaliação. + */ + public AvaliacaoInput(String observacaoAvaliacao, + String observacaoQuestao, + String questaoId, + Set competencias, + List infoCompetencias, + Integer confianca, + AvaliacaoPublicacao avaliacaoPublicacao) { + + this.observacaoAvaliacao = Optional.ofNullable(observacaoAvaliacao).orElse(""); + this.observacaoQuestao = Optional.ofNullable(observacaoQuestao).orElse(""); + this.questaoId = Optional.ofNullable(questaoId) + .filter(id -> !id.trim().isEmpty()) + .orElseThrow( + () -> new IllegalArgumentException("O identificador da questão não pode ser nulo ou vazio.")); + this.competencias = Optional.ofNullable(competencias) + .filter(comp -> !comp.isEmpty()) + .orElseThrow(() -> new IllegalArgumentException("Competências não podem ser nulas ou vazias.")); + this.infoCompetencias = Optional.ofNullable(infoCompetencias).orElse(Arrays.asList()); + this.confianca = Optional.ofNullable(confianca) + .filter(conf -> conf >= 0 && conf <= 100) + .orElseThrow(() -> new IllegalArgumentException("Confianca deve estar entre 0 e 100.")); + this.avaliacaoPublicacao = Optional.ofNullable(avaliacaoPublicacao) + .orElseThrow(() -> new IllegalArgumentException("AvaliacaoPublicacao não pode ser nula.")); } public String getObservacaoAvaliacao() { return observacaoAvaliacao; } - public void setObservacaoAvaliacao(String observacaoAvaliacao) { - this.observacaoAvaliacao = observacaoAvaliacao; - } - public String getObservacaoQuestao() { return observacaoQuestao; } - public void setObservacaoQuestao(String observacaoQuestao) { - this.observacaoQuestao = observacaoQuestao; - } - - public String getQuestao() { - return questao; - } - - public void setQuestao(String questao) { - this.questao = questao; + public String getQuestaoId() { + return questaoId; } public Set getCompetencias() { return competencias; } - public void setCompetencias(Set competencias) { - this.competencias = competencias; - } - public List getInfoCompetencias() { return infoCompetencias; } - public void setInfoCompetencias(List infoCompetencias) { - this.infoCompetencias = infoCompetencias; - } - public Integer getConfianca() { return confianca; } - public void setConfianca(Integer confianca) { - this.confianca = confianca; - } - public AvaliacaoPublicacao getAvaliacaoPublicacao() { return avaliacaoPublicacao; } - - public void setAvaliacaoPublicacao(AvaliacaoPublicacao avaliacaoPublicacao) { - this.avaliacaoPublicacao = avaliacaoPublicacao; - } } diff --git a/backend/src/main/java/springboot/dto/input/ListaQuestoesInput.java b/backend/src/main/java/springboot/dto/input/ListaQuestoesInput.java index d5aa01d9..d39ec7e3 100644 --- a/backend/src/main/java/springboot/dto/input/ListaQuestoesInput.java +++ b/backend/src/main/java/springboot/dto/input/ListaQuestoesInput.java @@ -1,30 +1,51 @@ package springboot.dto.input; +import java.util.Collections; import java.util.List; - -public class ListaQuestoesInput { - - private String nomeLista; - private List questoes; - +import java.util.Optional; + +/** + * DTO para representar a entrada de dados de uma lista de questões. + */ +public final class ListaQuestoesInput { + + private final String nomeLista; + private final List questoes; + + /** + * Construtor para inicializar uma ListaQuestoesInput. + * + * @param nomeLista O nome da lista de questões. + * @param questoes A lista de identificadores de questões. Não pode ser nula ou + * vazia. + * @throws IllegalArgumentException Se nomeLista for nulo ou vazio, ou se + * questoes for nulo ou vazio. + */ public ListaQuestoesInput(String nomeLista, List questoes) { - this.nomeLista = nomeLista; - this.questoes = questoes; + this.nomeLista = Optional.ofNullable(nomeLista) + .filter(nome -> !nome.trim().isEmpty()) + .orElseThrow(() -> new IllegalArgumentException("Nome da lista não pode ser nulo ou vazio.")); + this.questoes = Optional.ofNullable(questoes) + .filter(q -> !q.isEmpty()) + .map(Collections::unmodifiableList) + .orElseThrow(() -> new IllegalArgumentException("A lista de questões não pode ser nula ou vazia.")); } + /** + * Obtém o nome da lista de questões. + * + * @return O nome da lista. + */ public String getNomeLista() { return nomeLista; } - public void setNomeLista(String nomeLista) { - this.nomeLista = nomeLista; - } - + /** + * Obtém a lista de identificadores de questões. + * + * @return A lista de identificadores de questões. + */ public List getQuestoes() { return questoes; } - - public void setQuestoes(List questoes) { - this.questoes = questoes; - } } diff --git a/backend/src/main/java/springboot/dto/input/QuestaoInput.java b/backend/src/main/java/springboot/dto/input/QuestaoInput.java index f57faa7c..b89d6ceb 100644 --- a/backend/src/main/java/springboot/dto/input/QuestaoInput.java +++ b/backend/src/main/java/springboot/dto/input/QuestaoInput.java @@ -3,134 +3,126 @@ import springboot.enums.CompetenciaType; import springboot.model.Alternativa; -import java.util.HashSet; +import java.util.Collections; import java.util.List; -import java.util.Map; +import java.util.Optional; import java.util.Set; -public class QuestaoInput { - - private String tipo; - - private String enunciado; - - private Set competencias; - - private String fonte; - - private String espelho; - - private HashSet conteudo; - - private List alternativas; - - private Set competenciasAvaliacao; - - private List infoCompetenciasAvaliacao; - - private Integer confiancaAvaliacao; - - private String obsAvaliacao; - - public QuestaoInput(String tipo, String enunciado, Set competencias, String fonte, String espelho, HashSet conteudo, List alternativas, Set competenciasAvaliacao, List infoCompetenciasAvaliacao, Integer confiancaAvaliacao, String obsAvaliacao) { - this.tipo = tipo; - this.enunciado = enunciado; - this.competencias = competencias; +/** + * DTO para representar a entrada de dados de uma questão. + */ +public final class QuestaoInput { + + private final String tipo; + private final String enunciado; + private final Set competencias; + private final String fonte; + private final String espelho; + private final Set conteudo; + private final List alternativas; + private final Set competenciasAvaliacao; + private final List infoCompetenciasAvaliacao; + private final Integer confiancaAvaliacao; + private final String obsAvaliacao; + + /** + * Construtor para inicializar um QuestaoInput. + * + * @param tipo O tipo da questão. + * @param enunciado O enunciado ou descrição da questão. + * @param competencias O conjunto de competências associadas à + * questão. + * @param fonte A fonte ou referência da questão. + * @param espelho A resposta ou explicação detalhada da + * questão. + * @param conteudo O conjunto de conteúdos relacionados à + * questão. + * @param alternativas A lista de alternativas possíveis para a + * questão. + * @param competenciasAvaliacao As competências atribuídas na avaliação da + * questão. + * @param infoCompetenciasAvaliacao Informações adicionais sobre as competências + * avaliadas. + * @param confiancaAvaliacao O nível de confiança na avaliação. + * @param obsAvaliacao Observações relacionadas à avaliação da + * questão. + * @throws IllegalArgumentException Se algum parâmetro obrigatório for nulo ou + * inválido. + */ + public QuestaoInput(String tipo, String enunciado, Set competencias, String fonte, + String espelho, Set conteudo, List alternativas, + Set competenciasAvaliacao, List infoCompetenciasAvaliacao, + Integer confiancaAvaliacao, String obsAvaliacao) { + + this.tipo = Optional.ofNullable(tipo) + .filter(t -> !t.trim().isEmpty()) + .orElseThrow(() -> new IllegalArgumentException("O tipo não pode ser nulo ou vazio.")); + this.enunciado = Optional.ofNullable(enunciado) + .filter(e -> !e.trim().isEmpty()) + .orElseThrow(() -> new IllegalArgumentException("O enunciado não pode ser nulo ou vazio.")); + this.competencias = Optional.ofNullable(competencias) + .orElseThrow(() -> new IllegalArgumentException("Competências não podem ser nulas.")); + this.conteudo = Optional.ofNullable(conteudo) + .map(Collections::unmodifiableSet) + .orElseThrow(() -> new IllegalArgumentException("Conteúdo não pode ser nulo.")); this.fonte = fonte; this.espelho = espelho; - this.conteudo = conteudo; - this.alternativas = alternativas; this.competenciasAvaliacao = competenciasAvaliacao; this.infoCompetenciasAvaliacao = infoCompetenciasAvaliacao; this.confiancaAvaliacao = confiancaAvaliacao; this.obsAvaliacao = obsAvaliacao; + + if (!"Subjetiva".equalsIgnoreCase(tipo)) { + this.alternativas = Optional.ofNullable(alternativas) + .map(Collections::unmodifiableList) + .orElseThrow(() -> new IllegalArgumentException( + "Alternativas não podem ser nulas para questões objetivas.")); + } else { + this.alternativas = alternativas; // Pode ser nulo para questões subjetivas + } } public String getTipo() { return tipo; } - public void setTipo(String tipo) { - this.tipo = tipo; - } - public String getEnunciado() { return enunciado; } - public void setEnunciado(String enunciado) { - this.enunciado = enunciado; - } - public Set getCompetencias() { return competencias; } - public void setCompetencias(Set competencias) { - this.competencias = competencias; - } - public String getFonte() { return fonte; } - public void setFonte(String fonte) { - this.fonte = fonte; - } - public String getEspelho() { return espelho; } - public void setEspelho(String espelho) { - this.espelho = espelho; - } - - public HashSet getConteudo() { + public Set getConteudo() { return conteudo; } - public void setConteudo(HashSet conteudo) { - this.conteudo = conteudo; - } - public List getAlternativas() { return alternativas; } - public void setAlternativas(List alternativas) { - this.alternativas = alternativas; - } - public Set getCompetenciasAvaliacao() { return competenciasAvaliacao; } - public void setCompetenciasAvaliacao(Set competenciasAvaliacao) { - this.competenciasAvaliacao = competenciasAvaliacao; - } - public List getInfoCompetenciasAvaliacao() { return infoCompetenciasAvaliacao; } - public void setInfoCompetenciasAvaliacao(List infoCompetenciasAvaliacao) { - this.infoCompetenciasAvaliacao = infoCompetenciasAvaliacao; - } - public Integer getConfiancaAvaliacao() { return confiancaAvaliacao; } - public void setConfiancaAvaliacao(Integer conviancaAvaliacao) { - this.confiancaAvaliacao = conviancaAvaliacao; - } - public String getObsAvaliacao() { return obsAvaliacao; } - - public void setObsAvaliacao(String obsAvaliacao) { - this.obsAvaliacao = obsAvaliacao; - } } diff --git a/backend/src/main/java/springboot/dto/input/UsuarioInput.java b/backend/src/main/java/springboot/dto/input/UsuarioInput.java index 426f0c59..8afb62d4 100644 --- a/backend/src/main/java/springboot/dto/input/UsuarioInput.java +++ b/backend/src/main/java/springboot/dto/input/UsuarioInput.java @@ -1,57 +1,64 @@ package springboot.dto.input; import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Optional; -public class UsuarioInput { +/** + * DTO para representar a entrada de dados de um usuário. + */ +public final class UsuarioInput { @JsonProperty("cargo") - String cargo; + private final String cargo; @JsonProperty("cidade") - String cidade; + private final String cidade; @JsonProperty("idade") - int idade; + private final int idade; @JsonProperty("nomeInstituicao") - String nomeInstituicao; + private final String nomeInstituicao; - public UsuarioInput( String cargo, String cidade, int idade, String nomeInstituicao) { - this.cargo = cargo; - this.cidade = cidade; + /** + * Construtor para inicializar um UsuarioInput. + * + * @param cargo O cargo ou função do usuário. + * @param cidade A cidade de residência do usuário. + * @param idade A idade do usuário. + * @param nomeInstituicao O nome da instituição associada ao usuário. + * @throws IllegalArgumentException Se algum parâmetro obrigatório for nulo ou + * inválido. + */ + public UsuarioInput(String cargo, String cidade, int idade, String nomeInstituicao) { + this.cargo = Optional.ofNullable(cargo) + .filter(c -> !c.trim().isEmpty()) + .orElseThrow(() -> new IllegalArgumentException("O cargo não pode ser nulo ou vazio.")); + this.cidade = Optional.ofNullable(cidade) + .filter(c -> !c.trim().isEmpty()) + .orElseThrow(() -> new IllegalArgumentException("A cidade não pode ser nula ou vazia.")); + if (idade < 0) { + throw new IllegalArgumentException("A idade não pode ser negativa."); + } this.idade = idade; - this.nomeInstituicao = nomeInstituicao; + this.nomeInstituicao = Optional.ofNullable(nomeInstituicao) + .filter(n -> !n.trim().isEmpty()) + .orElseThrow(() -> new IllegalArgumentException("O nome da instituição não pode ser nulo ou vazio.")); } public String getCargo() { return cargo; } - public void setCargo(String cargo) { - this.cargo = cargo; - } - public String getCidade() { return cidade; } - public void setCidade(String cidade) { - this.cidade = cidade; - } - public int getIdade() { return idade; } - public void setIdade(int idade) { - this.idade = idade; - } - public String getNomeInstituicao() { return nomeInstituicao; } - - public void setNomeInstituicao(String nomeInstituicao) { - this.nomeInstituicao = nomeInstituicao; - } } diff --git a/backend/src/main/java/springboot/dto/output/CursoOutput.java b/backend/src/main/java/springboot/dto/output/CursoOutput.java index 8b9bf45f..8923b04c 100644 --- a/backend/src/main/java/springboot/dto/output/CursoOutput.java +++ b/backend/src/main/java/springboot/dto/output/CursoOutput.java @@ -1,8 +1,5 @@ package springboot.dto.output; -import springboot.model.ModuloCurso; -import springboot.model.Questao; - import java.util.ArrayList; import java.util.List; @@ -21,7 +18,7 @@ public CursoOutput(String mensagem, List cursoAvaliacao, List public CursoOutput() { this.cursoAvaliacao = new ArrayList<>(); - this.cursoCriacao = cursoCriacao; + this.cursoCriacao = new ArrayList<>(); } public String getMensagem() { diff --git a/backend/src/main/java/springboot/dto/output/ListaQuestoesOutput.java b/backend/src/main/java/springboot/dto/output/ListaQuestoesOutput.java index 05dbe5de..87ae0029 100644 --- a/backend/src/main/java/springboot/dto/output/ListaQuestoesOutput.java +++ b/backend/src/main/java/springboot/dto/output/ListaQuestoesOutput.java @@ -1,9 +1,6 @@ package springboot.dto.output; -import springboot.model.ListaQuestoes; import springboot.model.Questao; -import springboot.model.Usuario; - import java.util.List; public class ListaQuestoesOutput { diff --git a/backend/src/main/java/springboot/dto/output/ModuloCursoOutput.java b/backend/src/main/java/springboot/dto/output/ModuloCursoOutput.java index 93c4b8f2..c9acb4f3 100644 --- a/backend/src/main/java/springboot/dto/output/ModuloCursoOutput.java +++ b/backend/src/main/java/springboot/dto/output/ModuloCursoOutput.java @@ -1,8 +1,6 @@ package springboot.dto.output; import springboot.model.ModuloCurso; -import springboot.model.Questao; - import java.util.ArrayList; import java.util.List; From 5e89495620ea9382d051f649e9c77ea05587d7de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Vitor?= Date: Tue, 17 Sep 2024 02:39:04 -0300 Subject: [PATCH 06/18] clean exception files --- .../exception/RestExceptionHandler.java | 24 ------------------- .../exception/auth/InvalidTokenException.java | 4 +++- .../auth/UserAlreadyExistException.java | 4 +++- .../data/NoPendentQuestionException.java | 4 +++- .../data/PermissionDeniedException.java | 4 +++- .../data/RegisterNotFoundException.java | 2 ++ 6 files changed, 14 insertions(+), 28 deletions(-) diff --git a/backend/src/main/java/springboot/exception/RestExceptionHandler.java b/backend/src/main/java/springboot/exception/RestExceptionHandler.java index 7ecd6bae..4fd2c5e7 100644 --- a/backend/src/main/java/springboot/exception/RestExceptionHandler.java +++ b/backend/src/main/java/springboot/exception/RestExceptionHandler.java @@ -50,28 +50,4 @@ public ResponseEntity handleNoPendentQuestionException(Excepti public ResponseEntity handleMailException(Exception ex) { return new ResponseEntity<>(new CustomRestOutput(ex), new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR); } - - /* - @ExceptionHandler(InvalidTokenExce.class) - public ResponseEntity handleWrongCredentialsException(Exception ex) { - return new ResponseEntity<>(new CustomRestOutput(ex), new HttpHeaders(), HttpStatus.BAD_REQUEST); - } - - @ExceptionHandler(InvalidDataException.class) - public ResponseEntity handleInvalidDataException(Exception ex) { - CustomRestError errorMessage = new CustomRestError(new Date(), ex.getMessage().getDescription(false)); - return new ResponseEntity<>(errorMessage, new HttpHeaders(), HttpStatus.UNPROCESSABLE_ENTITY); - } - - @ExceptionHandler(InvalidTokenException.class) - public ResponseEntity handleInvalidTokenException(Exception ex) { - CustomRestError errorMessage = new CustomRestError(new Date(), ex.getMessage().getDescription(false)); - return new ResponseEntity<>(errorMessage, new HttpHeaders(), HttpStatus.UNAUTHORIZED); - } - - @ExceptionHandler(NotAuthorizedException.class) - public ResponseEntity handleNotAuthorizedException(Exception ex) { - CustomRestError errorMessage = new CustomRestError(new Date(), ex.getMessage().getDescription(false)); - return new ResponseEntity<>(errorMessage, new HttpHeaders(), HttpStatus.UNAUTHORIZED); - }*/ } \ No newline at end of file diff --git a/backend/src/main/java/springboot/exception/auth/InvalidTokenException.java b/backend/src/main/java/springboot/exception/auth/InvalidTokenException.java index 89801de0..662a0aee 100644 --- a/backend/src/main/java/springboot/exception/auth/InvalidTokenException.java +++ b/backend/src/main/java/springboot/exception/auth/InvalidTokenException.java @@ -1,7 +1,9 @@ package springboot.exception.auth; public class InvalidTokenException extends RuntimeException { - public InvalidTokenException() { + private static final long serialVersionUID = 5907806120761844240L; + + public InvalidTokenException() { super("Token inválido ou expirado!"); } } diff --git a/backend/src/main/java/springboot/exception/auth/UserAlreadyExistException.java b/backend/src/main/java/springboot/exception/auth/UserAlreadyExistException.java index 71278b31..02b3f950 100644 --- a/backend/src/main/java/springboot/exception/auth/UserAlreadyExistException.java +++ b/backend/src/main/java/springboot/exception/auth/UserAlreadyExistException.java @@ -1,7 +1,9 @@ package springboot.exception.auth; public class UserAlreadyExistException extends RuntimeException { - public UserAlreadyExistException() { + private static final long serialVersionUID = 7291385226058269111L; + + public UserAlreadyExistException() { super("Já existe um usuário cadastrado com este email!"); } } diff --git a/backend/src/main/java/springboot/exception/data/NoPendentQuestionException.java b/backend/src/main/java/springboot/exception/data/NoPendentQuestionException.java index 5464ec37..40857c69 100644 --- a/backend/src/main/java/springboot/exception/data/NoPendentQuestionException.java +++ b/backend/src/main/java/springboot/exception/data/NoPendentQuestionException.java @@ -1,7 +1,9 @@ package springboot.exception.data; public class NoPendentQuestionException extends RuntimeException { - public NoPendentQuestionException(String message) { + private static final long serialVersionUID = 1481888860192498156L; + + public NoPendentQuestionException(String message) { super(message); } } diff --git a/backend/src/main/java/springboot/exception/data/PermissionDeniedException.java b/backend/src/main/java/springboot/exception/data/PermissionDeniedException.java index 0e68c77a..e2c16c51 100644 --- a/backend/src/main/java/springboot/exception/data/PermissionDeniedException.java +++ b/backend/src/main/java/springboot/exception/data/PermissionDeniedException.java @@ -1,7 +1,9 @@ package springboot.exception.data; public class PermissionDeniedException extends RuntimeException { - public PermissionDeniedException(String message) { + private static final long serialVersionUID = 2035267621092903695L; + + public PermissionDeniedException(String message) { super(message); } } diff --git a/backend/src/main/java/springboot/exception/data/RegisterNotFoundException.java b/backend/src/main/java/springboot/exception/data/RegisterNotFoundException.java index 690509d9..466c77f4 100644 --- a/backend/src/main/java/springboot/exception/data/RegisterNotFoundException.java +++ b/backend/src/main/java/springboot/exception/data/RegisterNotFoundException.java @@ -1,6 +1,8 @@ package springboot.exception.data; public class RegisterNotFoundException extends RuntimeException { + private static final long serialVersionUID = 7218176289464335813L; + public RegisterNotFoundException(String message) { super(message); } From c8182dad8630fbe6e717d4e3f33f5715fd1d994c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Vitor?= Date: Tue, 17 Sep 2024 02:42:43 -0300 Subject: [PATCH 07/18] clean model files --- .../java/springboot/model/Alternativa.java | 96 ++++------ .../main/java/springboot/model/Avaliacao.java | 123 ++++++++----- .../main/java/springboot/model/Conteudo.java | 15 +- .../src/main/java/springboot/model/Curso.java | 18 +- .../src/main/java/springboot/model/Email.java | 97 ++++++---- .../java/springboot/model/ListaQuestoes.java | 50 ++++-- .../java/springboot/model/ModuloCurso.java | 35 ++-- .../main/java/springboot/model/Questao.java | 166 ++++++------------ .../main/java/springboot/model/Usuario.java | 84 +++++---- 9 files changed, 340 insertions(+), 344 deletions(-) diff --git a/backend/src/main/java/springboot/model/Alternativa.java b/backend/src/main/java/springboot/model/Alternativa.java index 101d627c..05282233 100644 --- a/backend/src/main/java/springboot/model/Alternativa.java +++ b/backend/src/main/java/springboot/model/Alternativa.java @@ -1,54 +1,35 @@ package springboot.model; - - -import javax.validation.constraints.NotNull; - -import org.springframework.data.annotation.Id; -import org.springframework.data.mongodb.core.index.Indexed; -import org.springframework.data.mongodb.core.mapping.Document; - +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; /** - * Classe responsavel por conter metodos e atributos de um objeto do tipo Alternativa. - * + * Classe responsável por conter métodos e atributos de um objeto do tipo + * Alternativa. + * * Ambiente de Estudo ao Pensamento Computacional * - * @author Marcelo Gabriel dos Santos Queiroz Vitorino + * @author Marcelo Gabriel dos Santos Queiroz Vitorino */ - - public class Alternativa { + @NotBlank(message = "O texto da alternativa não pode estar vazio") + private final String texto; - @NotNull - private String texto; + @NotNull(message = "A veracidade da alternativa deve ser informada") + private final Boolean correta; - @NotNull - private boolean correta; - - /** * Cria uma alternativa com texto e informação se é correta. * - * @param texto - * O texto da alternativa. - * @param correta - * A veracidade da alternativa. - * + * @param texto O texto da alternativa. + * @param correta A veracidade da alternativa. */ - public Alternativa(String texto, boolean correta) { + public Alternativa(String texto, Boolean correta) { this.texto = texto; this.correta = correta; } - public Alternativa() { - - } - - - - /** * Recupera o texto da alternativa. * @@ -57,43 +38,44 @@ public Alternativa() { public String getTexto() { return texto; } - /** - * @param texto - * O texto da alternativa. - * - * Atualiza o texto da alternativa. - * - */ - public void setTexto(String texto) { - this.texto = texto; - } /** * Recupera a veracidade da alternativa. * - * @return O valor true ou false da veraciadade da alternativa. + * @return O valor true ou false da veracidade da alternativa. */ - public boolean isCorreta() { + public Boolean isCorreta() { return correta; } + /** - * @param correta - * O valor true ou false da veraciadade da alternativa. - * - * Atualiza a veracidade da alternativa. - * - */ - public void setCorreta(boolean correta) { - this.correta = correta; - } - /** - * Representacao em string da alternativa. + * Representação em string da alternativa. * - * @return A representacao em string da alternativa. + * @return A representação em string da alternativa. */ @Override public String toString() { - return "Alternativa [texto=" + texto + ", correta=" + correta + "]"; + return "Alternativa [texto=".concat(texto).concat(", correta=").concat(String.valueOf(correta)).concat("]"); + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + Alternativa that = (Alternativa) o; + + if (!texto.equals(that.texto)) + return false; + return correta.equals(that.correta); } + @Override + public int hashCode() { + int result = texto.hashCode(); + result = 31 * result + correta.hashCode(); + return result; + } } diff --git a/backend/src/main/java/springboot/model/Avaliacao.java b/backend/src/main/java/springboot/model/Avaliacao.java index 3bca4d73..dfee6638 100644 --- a/backend/src/main/java/springboot/model/Avaliacao.java +++ b/backend/src/main/java/springboot/model/Avaliacao.java @@ -1,42 +1,52 @@ package springboot.model; -import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; +import java.util.Set; + import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.index.TextIndexed; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; import springboot.enums.AvaliacaoPublicacao; import springboot.enums.CompetenciaType; -import javax.validation.constraints.NotNull; -import java.util.List; -import java.util.Map; -import java.util.Set; - public class Avaliacao { + @Id @JsonProperty private String id; @NotNull @TextIndexed - private String observacaoAvaliacao; + @NotBlank(message = "A observação da avaliação não pode estar em branco") + private final String observacaoAvaliacao; @TextIndexed - private String observacaoQuestao; + private final String observacaoQuestao; @TextIndexed - private Set competencias; + private final Set competencias; - private List infoCompetencias; + private final List infoCompetencias; - private String autor; + @NotBlank(message = "O autor não pode estar em branco") + private final String autor; - private String questao; + @NotBlank(message = "A questão não pode estar em branco") + private final String questao; - private Integer confianca; + private final Integer confianca; - private AvaliacaoPublicacao avaliacaoPublicacao; + @NotNull(message = "A publicação da avaliação não pode ser nula") + private final AvaliacaoPublicacao avaliacaoPublicacao; - public Avaliacao(String observacaoAvaliacao, String observacaoQuestao, Set competencias, List infoCompetencias, String autor, String questao, Integer confianca, AvaliacaoPublicacao avaliacaoPublicacao) { + // Construtor imutável + public Avaliacao(String observacaoAvaliacao, String observacaoQuestao, Set competencias, + List infoCompetencias, String autor, String questao, Integer confianca, + AvaliacaoPublicacao avaliacaoPublicacao) { this.observacaoAvaliacao = observacaoAvaliacao; this.observacaoQuestao = observacaoQuestao; this.competencias = competencias; @@ -45,6 +55,7 @@ public Avaliacao(String observacaoAvaliacao, String observacaoQuestao, Set getCompetencias() { return competencias; } - public void setCompetencias(Set competencias) { - this.competencias = competencias; - } - public List getInfoCompetencias() { return infoCompetencias; } - public void setInfoCompetencias(List infoCompetencias) { - this.infoCompetencias = infoCompetencias; - } - public String getAutor() { return autor; } - public void setAutor(String autor) { - this.autor = autor; - } - public String getQuestao() { return questao; } - public void setQuestao(String questao) { - this.questao = questao; - } - public Integer getConfianca() { return confianca; } - public void setConfianca(Integer confianca) { - this.confianca = confianca; - } - public AvaliacaoPublicacao getAvaliacaoPublicacao() { return avaliacaoPublicacao; } - public void setAvaliacaoPublicacao(AvaliacaoPublicacao avaliacaoPublicacao) { - this.avaliacaoPublicacao = avaliacaoPublicacao; + @Override + public String toString() { + return "Avaliacao{".concat( + "id='").concat(id).concat("', observacaoAvaliacao='").concat(observacaoAvaliacao) + .concat("', observacaoQuestao='").concat(observacaoQuestao).concat("', competencias=") + .concat(competencias.toString()).concat(", infoCompetencias=").concat(infoCompetencias.toString()) + .concat(", autor='") + .concat(autor).concat("', questao='").concat(questao).concat("', confianca=") + .concat(confianca.toString()) + .concat(", avaliacaoPublicacao=").concat(avaliacaoPublicacao.toString()).concat("}"); + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + Avaliacao avaliacao = (Avaliacao) o; + + if (!id.equals(avaliacao.id)) + return false; + if (!observacaoAvaliacao.equals(avaliacao.observacaoAvaliacao)) + return false; + if (!observacaoQuestao.equals(avaliacao.observacaoQuestao)) + return false; + if (!competencias.equals(avaliacao.competencias)) + return false; + if (!infoCompetencias.equals(avaliacao.infoCompetencias)) + return false; + if (!autor.equals(avaliacao.autor)) + return false; + if (!questao.equals(avaliacao.questao)) + return false; + if (!confianca.equals(avaliacao.confianca)) + return false; + return avaliacaoPublicacao == avaliacao.avaliacaoPublicacao; + } + + @Override + public int hashCode() { + int result = id.hashCode(); + result = 31 * result + observacaoAvaliacao.hashCode(); + result = 31 * result + observacaoQuestao.hashCode(); + result = 31 * result + competencias.hashCode(); + result = 31 * result + infoCompetencias.hashCode(); + result = 31 * result + autor.hashCode(); + result = 31 * result + questao.hashCode(); + result = 31 * result + confianca.hashCode(); + result = 31 * result + avaliacaoPublicacao.hashCode(); + return result; } } diff --git a/backend/src/main/java/springboot/model/Conteudo.java b/backend/src/main/java/springboot/model/Conteudo.java index 88718fe7..74bf31ec 100644 --- a/backend/src/main/java/springboot/model/Conteudo.java +++ b/backend/src/main/java/springboot/model/Conteudo.java @@ -1,24 +1,19 @@ package springboot.model; -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; import org.springframework.data.annotation.Id; +import com.fasterxml.jackson.annotation.JsonProperty; + public class Conteudo { @Id - private String nome; + private final String nome; - @JsonCreator - public Conteudo(@JsonProperty("nome")String nome) { + public Conteudo(@JsonProperty("nome") String nome) { this.nome = nome; } - + @JsonProperty("nome") public String getNome() { return nome; } - - public void setNome(String nome) { - this.nome = nome; - } } diff --git a/backend/src/main/java/springboot/model/Curso.java b/backend/src/main/java/springboot/model/Curso.java index 86c51843..7d65302e 100644 --- a/backend/src/main/java/springboot/model/Curso.java +++ b/backend/src/main/java/springboot/model/Curso.java @@ -7,14 +7,14 @@ public class Curso { private String descricao; - private List exemplos; //Tambem são videos + private List videoExemplos; - private List textoExemplos; //No mesmo formato da descrição + private List textoExemplos; - public Curso(String video, String descricao, List exemplos, List textoExemplos) { + public Curso(String video, String descricao, List videoExemplos, List textoExemplos) { this.video = video; this.descricao = descricao; - this.exemplos = exemplos; + this.videoExemplos = videoExemplos; this.textoExemplos = textoExemplos; } @@ -37,12 +37,12 @@ public void setDescricao(String descricao) { this.descricao = descricao; } - public List getExemplos() { - return exemplos; + public List getVideoExemplos() { + return videoExemplos; } - public void setExemplos(List exemplos) { - this.exemplos = exemplos; + public void setVideoExemplos(List videoExemplos) { + this.videoExemplos = videoExemplos; } public List getTextoExemplos() { @@ -52,4 +52,4 @@ public List getTextoExemplos() { public void setTextoExemplos(List textoExemplos) { this.textoExemplos = textoExemplos; } -} +} \ No newline at end of file diff --git a/backend/src/main/java/springboot/model/Email.java b/backend/src/main/java/springboot/model/Email.java index 638b632b..3708169f 100644 --- a/backend/src/main/java/springboot/model/Email.java +++ b/backend/src/main/java/springboot/model/Email.java @@ -1,62 +1,81 @@ package springboot.model; -import javax.xml.bind.annotation.XmlRootElement; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; -@XmlRootElement public class Email { - private String username; - - private String email; - - private String subject; - - private String message; - - public Email() { - - } - - public Email(String username,String email, String subject, String message) { - this.username = username; - this.email = email; - this.subject = subject; - this.message = message; - } + @NotBlank(message = "Username cannot be blank") + @Size(max = 100, message = "Username must be less than 100 characters") + private final String username; - public String getUsername() { - return username; - } + @NotBlank(message = "Email cannot be blank") + @jakarta.validation.constraints.Email(message = "Invalid email format") + private final String email; + + @NotBlank(message = "Subject cannot be blank") + @Size(max = 200, message = "Subject must be less than 200 characters") + private final String subject; - public void setUsername(String username) { + @NotBlank(message = "Message cannot be blank") + private final String message; + + public Email(String username, String email, String subject, String message) { this.username = username; + this.email = email; + this.subject = subject; + this.message = message; } - public String getEmail() { - return email; + public String getUsername() { + return username; } - public void setEmail(String email) { - this.email = email; + public String getEmail() { + return email; } public String getSubject() { return subject; } - public void setSubject(String subject) { - this.subject = subject; - } - public String getMessage() { return message; } - public void setMessage(String message) { - this.message = message; + @Override + public String toString() { + return "Email{".concat( + "username='").concat(username).concat("', email='") + .concat(email).concat("', subject='") + .concat(subject).concat("', message='") + .concat(message).concat("'}"); + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + Email email1 = (Email) o; + + if (!username.equals(email1.username)) + return false; + if (!email.equals(email1.email)) + return false; + if (!subject.equals(email1.subject)) + return false; + return message.equals(email1.message); + } + + @Override + public int hashCode() { + int result = username.hashCode(); + result = 31 * result + email.hashCode(); + result = 31 * result + subject.hashCode(); + result = 31 * result + message.hashCode(); + return result; } - - - - -} \ No newline at end of file +} diff --git a/backend/src/main/java/springboot/model/ListaQuestoes.java b/backend/src/main/java/springboot/model/ListaQuestoes.java index 63ec8d7a..5dd618d5 100644 --- a/backend/src/main/java/springboot/model/ListaQuestoes.java +++ b/backend/src/main/java/springboot/model/ListaQuestoes.java @@ -1,36 +1,48 @@ package springboot.model; +import java.util.Collections; import java.util.List; - - -import javax.validation.constraints.NotNull; - import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.index.TextIndexed; import org.springframework.data.mongodb.core.mapping.Document; -// import org.springframework.data.mongodb.core.mapping.TextScore; - +import org.springframework.data.mongodb.core.mapping.TextScore; import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; + +/** + * Representa uma lista de questões associada a um autor, armazenada no MongoDB. + */ @Document(collection = "listaquestoes") -public class ListaQuestoes{ - +public class ListaQuestoes { + @Id @JsonProperty private String id; @NotNull @TextIndexed + @NotBlank(message = "O nome da lista não pode estar em branco") private String nomeLista; + @NotNull + @NotBlank(message = "O autor da lista não pode estar em branco") private String autor; - private List questoes; - - // @TextScore - // private Float score; + @TextScore + private Float score; + + /** + * Construtor para criar uma lista de questões com nome, autor e questões + * associadas. + * + * @param nomeLista O nome da lista de questões. + * @param autor O autor que criou a lista de questões. + * @param questoes Uma lista de IDs das questões. + */ public ListaQuestoes(String nomeLista, String autor, List questoes) { this.nomeLista = nomeLista; this.autor = autor; @@ -38,7 +50,7 @@ public ListaQuestoes(String nomeLista, String autor, List questoes) { } public ListaQuestoes() { - + this.questoes = Collections.emptyList(); } public String getId() { @@ -73,11 +85,11 @@ public void setQuestoes(List questoes) { this.questoes = questoes; } - // public Float getScore() { - // return score; - // } + public Float getScore() { + return score; + } - // public void setScore(Float score) { - // this.score = score; - // } + public void setScore(Float score) { + this.score = score; + } } diff --git a/backend/src/main/java/springboot/model/ModuloCurso.java b/backend/src/main/java/springboot/model/ModuloCurso.java index f62add2f..2987f513 100644 --- a/backend/src/main/java/springboot/model/ModuloCurso.java +++ b/backend/src/main/java/springboot/model/ModuloCurso.java @@ -3,18 +3,23 @@ import java.util.ArrayList; import java.util.List; +/** + * Classe que representa um módulo de curso, com seu estado, questões associadas + * e erros. + */ public class ModuloCurso { private String nome; - private EstadoModulo estado; - - private Integer erros; - - private List questoes; // Questões que foram carregadas para receber resposta - - private int numeroExemplo; //Indica qual é o video de exemplo atual - + private int erros; + private List questoes; // IDs das questões + private int numeroExemplo; // Video de exemplo atual (pode não existir) + + /** + * Construtor para inicializar o módulo do curso com um nome. + * + * @param nome O nome do módulo. + */ public ModuloCurso(String nome) { this.nome = nome; this.estado = EstadoModulo.DESCRICAO; @@ -39,24 +44,20 @@ public void setEstado(EstadoModulo estado) { this.estado = estado; } - public Integer getErros() { + public int getErros() { return erros; } - public void setErros(Integer erros) { - this.erros = erros; - } - - public void addErro() { + public void incrementarErros() { this.erros++; } - public void zeraErros() { + public void resetarErros() { this.erros = 0; } public List getQuestoes() { - return questoes; + return new ArrayList<>(questoes); } public void setQuestoes(List questoes) { @@ -76,6 +77,6 @@ public enum EstadoModulo { DESCRICAO, EXEMPLOS, PRATICA, - FINALIZADO; + FINALIZADO } } diff --git a/backend/src/main/java/springboot/model/Questao.java b/backend/src/main/java/springboot/model/Questao.java index c777fc78..5870e3a6 100644 --- a/backend/src/main/java/springboot/model/Questao.java +++ b/backend/src/main/java/springboot/model/Questao.java @@ -5,27 +5,24 @@ import java.util.List; import java.util.Set; -import javax.validation.constraints.NotNull; - import org.springframework.data.annotation.Id; - -/** - * Classe abstrata que representa um molde de uma Questão, que pode ser Objetiva ou Subjetiva. - * - * Ambiente de Estudo ao Pensamento Computacional - * - * @author Marcelo Gabriel dos Santos Queiroz Vitorino - */ - import org.springframework.data.mongodb.core.index.TextIndexed; import org.springframework.data.mongodb.core.mapping.Document; -// import org.springframework.data.mongodb.core.mapping.TextScore; +import org.springframework.data.mongodb.core.mapping.TextScore; import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.constraints.NotBlank; import springboot.enums.CompetenciaType; import springboot.enums.EstadoQuestao; +/** + * Classe que representa uma Questão que pode ser do tipo Objetiva ou Subjetiva. + * + * Ambiente de Estudo ao Pensamento Computacional + * + * Autor: Marcelo Gabriel dos Santos Queiroz Vitorino + */ @Document(collection = "questao") public class Questao { @@ -33,70 +30,61 @@ public class Questao { @JsonProperty private String id; - @NotNull + @NotBlank(message = "O tipo da questão não pode ser vazio") private String tipo; - @NotNull + @NotBlank(message = "O enunciado da questão não pode ser vazio") @TextIndexed private String enunciado; - private String originalEnunciado; - @TextIndexed - private Set competencias; + private Set competencias = new HashSet<>(); - private Set competenciasClassificador; + private Set competenciasClassificador = new HashSet<>(); + private String originalEnunciado; private String fonte; - private String autor; - private String espelho; - - private HashSet conteudo; + private Set conteudo = new HashSet<>(); private List alternativas; + private Integer qtdAvaliacoes = 0; + private Long ultimoAcesso = System.currentTimeMillis(); + private EstadoQuestao estado = EstadoQuestao.RASCUNHO; - private Integer qtdAvaliacoes; - - private Long ultimoAcesso; - - private EstadoQuestao estado; - - // @TextScore - // private Float score; + @TextScore + private Float score; /** - * Cria uma Questão com tipo, enunciado, fonte, autor e imagem. + * Construtor com parâmetros para criação de uma nova Questão. * - * @param tipo O tipo da questão. - * @param enunciado O enunciado da questão. - * @param fonte A fonte da questão. - * @param autor O autor da questão. - * @param espelho A imagem da questão. - * - * + * @param tipo O tipo da questão. + * @param conteudo O conteúdo da questão. + * @param enunciado O enunciado da questão. + * @param fonte A fonte da questão. + * @param autor O autor da questão. + * @param espelho A imagem espelho da questão. + * @param alternativas As alternativas da questão. + * @param competencias As competências relacionadas à questão. */ - public Questao(String tipo, HashSet conteudo, String enunciado, String fonte, String autor, String espelho, + public Questao(String tipo, Set conteudo, String enunciado, String fonte, String autor, String espelho, List alternativas, Collection competencias) { - this.tipo = tipo; - this.conteudo = conteudo; + this.conteudo = conteudo != null ? conteudo : new HashSet<>(); this.enunciado = enunciado; this.originalEnunciado = enunciado; this.fonte = fonte; this.autor = autor; this.espelho = espelho; this.alternativas = alternativas; - this.competencias = new HashSet(competencias); - this.competenciasClassificador = new HashSet(competencias); - this.qtdAvaliacoes = 0; - this.ultimoAcesso = System.currentTimeMillis(); - this.estado = EstadoQuestao.RASCUNHO; + if (competencias != null) { + this.competencias = new HashSet<>(competencias); + this.competenciasClassificador = new HashSet<>(competencias); + } } public Questao() { - } public String getId() { @@ -107,71 +95,50 @@ public void setId(String id) { this.id = id; } - /** - * Recupera o tipo da questão. - * - * @return O tipo da questão. - */ public String getTipo() { return tipo; } - /** - * @param tipo O tipo da questão. - * - * Atualiza o tipo da questão. - * - */ public void setTipo(String tipo) { this.tipo = tipo; } - - - public HashSet getConteudo() { + public Set getConteudo() { return conteudo; } - public void setConteudo(HashSet conteudo) { + public void setConteudo(Set conteudo) { this.conteudo = conteudo; } + public String getEnunciado() { + return enunciado; + } + public void setEnunciado(String enunciado) { + this.enunciado = enunciado; + } + + public String getOriginalEnunciado() { + return originalEnunciado; + } + + public void setOriginalEnunciado(String originalEnunciado) { + this.originalEnunciado = originalEnunciado; + } - /** - * Recupera a fonte da questão. - * - * @return A fonte da questão. - */ public String getFonte() { return fonte; } - /** - * @param fonte A fonte da questão. - * - * Atualiza a fonte da questão. - * - */ public void setFonte(String fonte) { this.fonte = fonte; } - /** - * Recupera o autor da questão. - * - * @return O autor da questão. - */ public String getAutor() { return autor; } - /** - * @param autor O autor da questão. - * - * Atualiza o autor da questão. - * - */ public void setAutor(String autor) { this.autor = autor; } @@ -192,28 +159,10 @@ public void setAlternativas(List alternativas) { this.alternativas = alternativas; } - public String getEnunciado() { - return enunciado; - } - - - public void setEnunciado(String enunciado) { - this.enunciado = enunciado; - } - - public String getOriginalEnunciado() { - return originalEnunciado; - } - - public void setOriginalEnunciado(String originalEnunciado) { - this.originalEnunciado = originalEnunciado; - } - public Set getCompetencias() { return competencias; } - public void setCompetencias(Set competencias) { this.competencias = competencias; } @@ -226,14 +175,13 @@ public void setCompetenciasClassificador(Set competenciasClassi this.competenciasClassificador = competenciasClassificador; } - // public Float getScore() { - // return score; - // } - - // public void setScore(Float score) { - // this.score = score; - // } + public Float getScore() { + return score; + } + public void setScore(Float score) { + this.score = score; + } public Integer getQtdAvaliacoes() { return qtdAvaliacoes; diff --git a/backend/src/main/java/springboot/model/Usuario.java b/backend/src/main/java/springboot/model/Usuario.java index 2e7898a2..569e2aa5 100644 --- a/backend/src/main/java/springboot/model/Usuario.java +++ b/backend/src/main/java/springboot/model/Usuario.java @@ -1,12 +1,11 @@ package springboot.model; - -import javax.validation.constraints.NotNull; - import org.springframework.data.annotation.Id; -import org.springframework.data.mongodb.core.index.Indexed; -import org.springframework.data.mongodb.core.index.TextIndexed; import org.springframework.data.mongodb.core.mapping.Document; + +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; import springboot.enums.PermissaoType; import java.util.ArrayList; @@ -15,44 +14,36 @@ @Document(collection = "usuario") public class Usuario { - @NotNull - @TextIndexed + @NotBlank(message = "Nome não pode ser vazio") private String nome; - - @NotNull - @TextIndexed + + @NotNull(message = "Idade não pode ser nula") private int idade; - @NotNull - @TextIndexed + @NotBlank(message = "Nome da instituição não pode ser vazio") private String nomeInstituicao; - - @NotNull - @TextIndexed + + @NotBlank(message = "Cargo não pode ser vazio") private String cargo; - - @NotNull - @TextIndexed + + @NotBlank(message = "Cidade não pode ser vazia") private String cidade; - @NotNull - @TextIndexed - @Id + @Id + @Email(message = "E-mail deve ser válido") + @NotBlank(message = "E-mail não pode ser vazio") private String email; - @NotNull - @TextIndexed private boolean ativo; - @NotNull - @TextIndexed - private List permissoes; + private List permissoes = new ArrayList<>(); - private List cursoAvaliacao; + private List cursoAvaliacao = new ArrayList<>(); - private List cursoCriacao; + private List cursoCriacao = new ArrayList<>(); - public Usuario(String nome, int idade, String nomeInstituicao, String cargo, String cidade, String email, boolean ativo) { + public Usuario(String nome, int idade, String nomeInstituicao, String cargo, String cidade, String email, + boolean ativo) { this.nome = nome; this.idade = idade; this.nomeInstituicao = nomeInstituicao; @@ -60,18 +51,33 @@ public Usuario(String nome, int idade, String nomeInstituicao, String cargo, Str this.cidade = cidade; this.email = email; this.ativo = ativo; - this.permissoes = new ArrayList<>(); - if (email.equals("joao.luciano@ccc.ufcg.edu.br") || email.equals("aepc.lacina@gmail.com")) { + adicionarPermissoesPadrao(email); + } + + public Usuario() { + + } + + public Usuario(boolean ativo, String cargo, String cidade, String email, int idade, String nome, + String nomeInstituicao) { + this.ativo = ativo; + this.cargo = cargo; + this.cidade = cidade; + this.email = email; + this.idade = idade; + this.nome = nome; + this.nomeInstituicao = nomeInstituicao; + } + + private void adicionarPermissoesPadrao(String email) { + if (isEmailAdmin(email)) { permissoes.add(PermissaoType.ADMIN); permissoes.add(PermissaoType.JUDGE); } - this.cursoAvaliacao = new ArrayList<>(); - this.cursoCriacao = new ArrayList<>(); - } - public Usuario() { - + private boolean isEmailAdmin(String email) { + return "joao.luciano@ccc.ufcg.edu.br".equals(email) || "aepc.lacina@gmail.com".equals(email); } public String getNome() { @@ -81,7 +87,7 @@ public String getNome() { public void setNome(String nome) { this.nome = nome; } - + public int getIdade() { return idade; } @@ -181,7 +187,7 @@ public boolean equals(Object obj) { @Override public String toString() { - return "Usuario [nomeCompleto=" + nome + ", nomeInstituicao=" + nomeInstituicao + ", email=" + email + "]"; + return "Usuario [nome=".concat(nome).concat(", nomeInstituicao=").concat(nomeInstituicao).concat(", email=") + .concat(email).concat("]"); } - } From 1415924e7f8d05246bc4c73d4e381ea765a13ba3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Vitor?= Date: Tue, 17 Sep 2024 02:43:08 -0300 Subject: [PATCH 08/18] clean model files --- .../springboot/model/UsuarioPermissao.java | 56 ++++++------------- 1 file changed, 16 insertions(+), 40 deletions(-) diff --git a/backend/src/main/java/springboot/model/UsuarioPermissao.java b/backend/src/main/java/springboot/model/UsuarioPermissao.java index 2aa3b791..3a3dd4cf 100644 --- a/backend/src/main/java/springboot/model/UsuarioPermissao.java +++ b/backend/src/main/java/springboot/model/UsuarioPermissao.java @@ -1,36 +1,32 @@ package springboot.model; - import javax.persistence.EnumType; import javax.persistence.Enumerated; -import javax.validation.constraints.NotNull; - import org.springframework.data.annotation.Id; -import org.springframework.data.mongodb.core.index.Indexed; -import org.springframework.data.mongodb.core.index.TextIndexed; import org.springframework.data.mongodb.core.mapping.Document; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; import springboot.enums.PermissaoType; +import java.util.Objects; @Document(collection = "usuario-permissao") public class UsuarioPermissao { - - @NotNull + @Id - @TextIndexed + @Email(message = "E-mail deve ser válido") + @NotBlank(message = "E-mail não pode ser vazio") private String email; - - @Enumerated(EnumType.STRING) - @NotNull - @TextIndexed + + @Enumerated(EnumType.STRING) + @NotNull(message = "Permissão não pode ser nula") private PermissaoType permissao; - - + public UsuarioPermissao() { - } - + public UsuarioPermissao(String email, PermissaoType permissao) { this.email = email; this.permissao = permissao; @@ -54,41 +50,21 @@ public void setPermissao(PermissaoType permissao) { @Override public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((email == null) ? 0 : email.hashCode()); - result = prime * result + ((permissao == null) ? 0 : permissao.hashCode()); - return result; + return Objects.hash(email, permissao); } @Override public boolean equals(Object obj) { if (this == obj) return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) + if (obj == null || getClass() != obj.getClass()) return false; UsuarioPermissao other = (UsuarioPermissao) obj; - if (email == null) { - if (other.email != null) - return false; - } else if (!email.equals(other.email)) - return false; - if (permissao == null) { - if (other.permissao != null) - return false; - } else if (!permissao.equals(other.permissao)) - return false; - return true; + return Objects.equals(email, other.email) && permissao == other.permissao; } @Override public String toString() { - return "UsuarioPermissao [email=" + email + ", permissao=" + permissao + "]"; + return "UsuarioPermissao [email=".concat(email).concat(", permissao=").concat(permissao.toString()).concat("]"); } - - - - } From 39a796a92e2612b36ffaa6763535ffb1cffbcbca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Vitor?= Date: Tue, 17 Sep 2024 02:48:20 -0300 Subject: [PATCH 09/18] rewrite service files --- .../springboot/service/AvaliacaoService.java | 53 ++---- .../springboot/service/ConteudoService.java | 35 ++-- .../java/springboot/service/CursoService.java | 171 +++++++----------- .../java/springboot/service/EmailService.java | 26 +++ .../service/ListaQuestoesService.java | 95 +++------- .../springboot/service/QuestaoService.java | 51 +++--- .../service/UsuarioPermissaoService.java | 49 ++--- .../springboot/service/UsuarioService.java | 83 +++++---- 8 files changed, 235 insertions(+), 328 deletions(-) create mode 100644 backend/src/main/java/springboot/service/EmailService.java diff --git a/backend/src/main/java/springboot/service/AvaliacaoService.java b/backend/src/main/java/springboot/service/AvaliacaoService.java index 403da981..1cf6e03f 100644 --- a/backend/src/main/java/springboot/service/AvaliacaoService.java +++ b/backend/src/main/java/springboot/service/AvaliacaoService.java @@ -11,49 +11,39 @@ import springboot.repository.AvaliacaoRepository; import java.util.List; -import java.util.Optional; @Service public class AvaliacaoService { + @Autowired + private AvaliacaoRepository avaliacaoRepository; - private final String errorMessage = "Avaliação não está cadastrada."; + private static final String ERROR_MESSAGE = "Avaliação não está cadastrada."; - @Autowired - public AvaliacaoRepository avaliacaoRepository; + public AvaliacaoService() { + } + + public AvaliacaoService(AvaliacaoRepository avaliacaoRepository) { + this.avaliacaoRepository = avaliacaoRepository; + } public Avaliacao save(Avaliacao avaliacao) { - avaliacaoRepository.save(avaliacao); - return avaliacao; + return avaliacaoRepository.save(avaliacao); } public Avaliacao update(Avaliacao avaliacao, String id) { - Optional optAvaliacao = avaliacaoRepository.findById(id); + Avaliacao existingAvaliacao = findAvaliacaoById(id); - if (!optAvaliacao.isPresent()) { - throw new RegisterNotFoundException(errorMessage); - } - - avaliacao.setId(id); - - if (!avaliacao.getAutor().equals(optAvaliacao.get().getAutor())) { + if (!avaliacao.getAutor().equals(existingAvaliacao.getAutor())) { throw new PermissionDeniedException("A avaliação foi criada por outro usuário."); } - avaliacaoRepository.save(avaliacao); - - return avaliacao; + avaliacao.setId(id); + return avaliacaoRepository.save(avaliacao); } public Avaliacao delete(String id) { - Optional optAvaliacao = avaliacaoRepository.findById(id); - - if (!optAvaliacao.isPresent()) { - throw new RegisterNotFoundException(errorMessage); - } - - Avaliacao avaliacao = optAvaliacao.get(); + Avaliacao avaliacao = findAvaliacaoById(id); avaliacaoRepository.delete(avaliacao); - return avaliacao; } @@ -63,18 +53,15 @@ public Page getAll(int page, int size) { } public Avaliacao getById(String id) { - Optional optAvaliacao = avaliacaoRepository.findById(id); - - if (!optAvaliacao.isPresent()) { - throw new RegisterNotFoundException(errorMessage); - } - - return optAvaliacao.get(); + return findAvaliacaoById(id); } public List getAllByQuestao(String questao) { return avaliacaoRepository.getAllByQuestao(questao); } - + private Avaliacao findAvaliacaoById(String id) { + return avaliacaoRepository.findById(id) + .orElseThrow(() -> new RegisterNotFoundException(ERROR_MESSAGE)); + } } diff --git a/backend/src/main/java/springboot/service/ConteudoService.java b/backend/src/main/java/springboot/service/ConteudoService.java index 7d6fcbdb..f6defb8a 100644 --- a/backend/src/main/java/springboot/service/ConteudoService.java +++ b/backend/src/main/java/springboot/service/ConteudoService.java @@ -1,40 +1,30 @@ package springboot.service; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import springboot.exception.data.RegisterNotFoundException; import springboot.model.Conteudo; import springboot.repository.ConteudoRepository; import java.util.List; -import java.util.Optional; @Service public class ConteudoService { - private final String errorMessage = "Conteúdo ainda não registrado no sistema!"; + private static final String ERROR_MESSAGE = "Conteúdo ainda não registrado no sistema!"; - @Autowired - private ConteudoRepository conteudoRepository; + private final ConteudoRepository conteudoRepository; - public ConteudoService() { + public ConteudoService(ConteudoRepository conteudoRepository) { + this.conteudoRepository = conteudoRepository; } public Conteudo save(Conteudo conteudo) { - conteudoRepository.save(conteudo); - return conteudo; + return conteudoRepository.save(conteudo); } public Conteudo delete(String conteudoText) { - Optional optConteudo = conteudoRepository.findById(conteudoText); - - if (!optConteudo.isPresent()) { - throw new RegisterNotFoundException(errorMessage); - } - - Conteudo conteudo = optConteudo.get(); + Conteudo conteudo = findConteudoById(conteudoText); conteudoRepository.delete(conteudo); - return conteudo; } @@ -43,14 +33,11 @@ public List getAll() { } public Conteudo getById(String id) { - Optional optConteudo = conteudoRepository.findById(id); - - if (!optConteudo.isPresent()) { - throw new RegisterNotFoundException(errorMessage); - } - - Conteudo conteudo = optConteudo.get(); - return conteudo; + return findConteudoById(id); } + private Conteudo findConteudoById(String id) { + return conteudoRepository.findById(id) + .orElseThrow(() -> new RegisterNotFoundException(ERROR_MESSAGE)); + } } diff --git a/backend/src/main/java/springboot/service/CursoService.java b/backend/src/main/java/springboot/service/CursoService.java index b63a8553..bd5a96d6 100644 --- a/backend/src/main/java/springboot/service/CursoService.java +++ b/backend/src/main/java/springboot/service/CursoService.java @@ -63,8 +63,7 @@ public List processModules(List modules, CourseT for (int i = 0; i < modules.size() - 1; i++) { ModuloCurso module = modules.get(i); - @SuppressWarnings("unlikely-arg-type") - Curso course = courseType.equals("AVALIACAO") + Curso course = courseType.equals(CourseType.AVALIACAO) ? competenciaRepository.findById(module.getNome()).get().getCursoAvaliacao() : competenciaRepository.findById(module.getNome()).get().getCursoCriacao(); ModuloCursoOutput moduleOutput = createCourseModuleOutput(module, course, courseType); @@ -101,30 +100,25 @@ public List processModules(List modules, CourseT * @param evaluationMod O módulo final de avaliação. * @return Um objeto `ModuloCursoOutput` com as informações do módulo final. */ - @SuppressWarnings("unlikely-arg-type") private ModuloCursoOutput processFinalModule(ModuloCurso evaluationMod, CourseType type, Usuario user) { ModuloCursoOutput evaluationOutput = new ModuloCursoOutput(); evaluationOutput.setNome(evaluationMod.getNome()); evaluationOutput.setEstado(evaluationMod.getEstado()); if (evaluationMod.getEstado().equals(EstadoModulo.PRATICA)) { - if (type.equals("CRIACAO")) { - if (evaluationMod.getQuestoes().size() > 0) { - + if (type.equals(CourseType.CRIACAO)) { + if (!evaluationMod.getQuestoes().isEmpty()) { try { String question = evaluationMod.getQuestoes().get(0); evaluationOutput.getQuestoesDetalhadas().add(questionSearchController.getById(user, question)); - evaluationOutput.getQuestoes().add(question); - } catch (Exception e) { user.getCursoCriacao().get(10).getQuestoes().clear(); } } } else { evaluationMod.setQuestoes(new ArrayList<>()); - for (String comp : COMP_NAMES) { Questao sample = questaoService.getSample(comp); evaluationMod.getQuestoes().add(sample.getId()); @@ -153,17 +147,11 @@ private ModuloCursoOutput createCourseModuleOutput(ModuloCurso module, Curso cou output.setVideo(course.getVideo()); switch (module.getEstado()) { - case EXEMPLOS: - updateExamples(module, course, output); - break; - case PRATICA: - addPracticeDetails(module, course, output, courseType); - break; - case FINALIZADO: - addExamplesAndTexts(module, course, output); - break; - default: - break; + case EXEMPLOS -> updateExamples(module, course, output); + case PRATICA -> addPracticeDetails(module, course, output, courseType); + case FINALIZADO -> addExamplesAndTexts(course, output); + default -> { + } } return output; @@ -177,9 +165,9 @@ private ModuloCursoOutput createCourseModuleOutput(ModuloCurso module, Curso cou * @param output O objeto de saída a ser atualizado. */ private void updateExamples(ModuloCurso module, Curso course, ModuloCursoOutput output) { - int index = (module.getNumeroExemplo() + 1) % course.getExemplos().size(); + int index = (module.getNumeroExemplo() + 1) % course.getVideoExemplos().size(); module.setNumeroExemplo(index); - output.getExemplos().add(course.getExemplos().get(index)); + output.getExemplos().add(course.getVideoExemplos().get(index)); output.getTextoExemplos().add(course.getTextoExemplos().get(index)); } @@ -191,8 +179,8 @@ private void updateExamples(ModuloCurso module, Curso course, ModuloCursoOutput * @param output O objeto `ModuloCursoOutput` onde os exemplos e textos serão * adicionados. */ - private void addExamplesAndTexts(ModuloCurso module, Curso course, ModuloCursoOutput output) { - output.setExemplos(course.getExemplos()); + private void addExamplesAndTexts(Curso course, ModuloCursoOutput output) { + output.setExemplos(course.getVideoExemplos()); output.setTextoExemplos(course.getTextoExemplos()); } @@ -204,13 +192,12 @@ private void addExamplesAndTexts(ModuloCurso module, Curso course, ModuloCursoOu * @param output O objeto de saída a ser atualizado. * @param courseType O tipo de curso acessado. */ - @SuppressWarnings("unlikely-arg-type") private void addPracticeDetails(ModuloCurso module, Curso course, ModuloCursoOutput output, CourseType courseType) { int index = module.getNumeroExemplo(); - output.getExemplos().add(course.getExemplos().get(index)); + output.getExemplos().add(course.getVideoExemplos().get(index)); output.getTextoExemplos().add(course.getTextoExemplos().get(index)); - if (courseType.equals("AVALIACAO")) { + if (courseType.equals(CourseType.AVALIACAO)) { List samples = questaoService.getSamples(module.getNome()); for (Questao q : samples) { @@ -231,11 +218,11 @@ private void addPracticeDetails(ModuloCurso module, Curso course, ModuloCursoOut public ResponseEntity auxCursoAvaliacoes(@RequestAttribute(name = "usuario") Usuario user, String message) { if (isCourseListEmpty(user.getCursoAvaliacao())) - return new ResponseEntity(new CursoOutput(), HttpStatus.NOT_FOUND); + return new ResponseEntity<>(new CursoOutput(), HttpStatus.NOT_FOUND); List outputList = processModules(user.getCursoAvaliacao(), CourseType.AVALIACAO, user); - user = usuarioService.update(user, user.getEmail()); + usuarioService.update(user, user.getEmail()); return new ResponseEntity<>(new CursoOutput(message, outputList, null), HttpStatus.OK); } @@ -295,13 +282,13 @@ else if (type == CourseType.CRIACAO) public ResponseEntity auxCursoCriacao(@RequestAttribute(name = "usuario") Usuario user, String message) { if (isCourseListEmpty(user.getCursoCriacao())) - return new ResponseEntity(new CursoOutput(), HttpStatus.NOT_FOUND); + return new ResponseEntity<>(new CursoOutput(), HttpStatus.NOT_FOUND); List outputList = processModules(user.getCursoCriacao(), CourseType.CRIACAO, user); - user = usuarioService.update(user, user.getEmail()); + usuarioService.update(user, user.getEmail()); - return new ResponseEntity(new CursoOutput(message, null, outputList), HttpStatus.OK); + return new ResponseEntity<>(new CursoOutput(message, null, outputList), HttpStatus.OK); } /** @@ -318,18 +305,14 @@ public String processEvaluationModule(Usuario user, List answers, int i boolean sendToBack = false; switch (module.getEstado()) { - case DESCRICAO: - processStateDescription(module, index); - break; - case EXEMPLOS: - module.setEstado(EstadoModulo.PRATICA); - break; - case PRATICA: + case DESCRICAO -> processStateDescription(module, index); + case EXEMPLOS -> module.setEstado(EstadoModulo.PRATICA); + case PRATICA -> { message = processStatePractice(user, answers, index, module); sendToBack = checkNeedReturn(module); - break; - default: - break; + } + default -> { + } } user.getCursoAvaliacao().set(index, module); @@ -356,18 +339,14 @@ public String processModuleCreation(Usuario user, List answers, int inde String message = null; switch (module.getEstado()) { - case DESCRICAO: - processStateDescription(module, index); - break; - case EXEMPLOS: - module.setEstado(EstadoModulo.PRATICA); - break; - case PRATICA: + case DESCRICAO -> processStateDescription(module, index); + case EXEMPLOS -> module.setEstado(EstadoModulo.PRATICA); + case PRATICA -> { message = processStatePractice(user, answers, module, index); sendToBack = checkNeedReturn(module); - break; - default: - break; + } + default -> { + } } user.getCursoCriacao().set(index, module); @@ -404,9 +383,8 @@ private void processStateDescription(ModuloCurso module, int index) { * @return Mensagem de feedback para o usuário. */ private String processStatePractice(Usuario user, List answers, int index, ModuloCurso module) { - String message = null; - int total = 0; - int errors = 0; + int total; + int errors; if (index == user.getCursoAvaliacao().size() - 1) { total = 9; @@ -416,8 +394,7 @@ private String processStatePractice(Usuario user, List answers, int ind errors = evaluateIntermediateResponses(answers, module, total); } - message = checkForErrors(user, module, total, errors, index); - return message; + return checkForErrors(user, module, total, errors, index); } /** @@ -430,15 +407,10 @@ private String processStatePractice(Usuario user, List answers, int ind * @return Mensagem de feedback para o usuário. */ private String processStatePractice(Usuario user, List answers, ModuloCurso module, int index) { - String message = null; - - if (index != 10) { - message = evaluateCompetence(user, answers, module); - } else { - message = evaluateFinalQuestion(user, module); - } + if (index != 10) + return evaluateCompetence(user, answers, module); - return message; + return evaluateFinalQuestion(user, module); } /** @@ -452,13 +424,12 @@ private String processStatePractice(Usuario user, List answers, ModuloCu private int evaluateFinalAnswers(List answers, ModuloCurso module, int total) { int errors = 0; if (answers == null || answers.size() != total) { - return total; // Erro total + return total; } - for (int j = 0; j < total; j++) { - if (!answers.get(j).equals(questaoService.evaluateQuestao(COMP_NAMES[j], module.getQuestoes().get(j)))) { + for (int j = 0; j < total; j++) + if (!answers.get(j).equals(questaoService.evaluateQuestao(COMP_NAMES[j], module.getQuestoes().get(j)))) errors++; - } - } + return errors; } @@ -495,7 +466,7 @@ private String checkForErrors(Usuario user, ModuloCurso module, int total, int e if (100 * errors <= total * 30) { // Erros <= 30% module.setEstado(EstadoModulo.FINALIZADO); - module.zeraErros(); + module.resetarErros(); } else if (index == user.getCursoAvaliacao().size() - 1) { message = "Você obteve menos de 70% de acerto, tente novamente ou volte e estude mais um pouco sobre as competências!"; } else { @@ -514,23 +485,25 @@ private String checkForErrors(Usuario user, ModuloCurso module, int total, int e */ private String handleErrorModule(ModuloCurso module, String context) { String message; - module.addErro(); - - if (module.getErros() == 2) { - message = String.format( - "Percebemos que você teve dificuldade %s, por isso deve voltar e ver mais um exemplo!", - context.equals("Competencia") ? "com essa competência" - : "em identificar a competência nas questões apresentadas"); - module.setEstado(EstadoModulo.EXEMPLOS); - } else if (module.getErros() == 3) { - message = String.format( - "Como você não conseguiu identificar bem %s, veja uma nova competência e depois tentaremos essa novamente!", - context.equals("Competencia") ? "a competência" - : "a presença ou ausência da competência nas questões apresentadas"); - module.zeraErros(); - module.setEstado(EstadoModulo.DESCRICAO); - } else { - message = String.format("%s, tente novamente!", + module.incrementarErros(); + + switch (module.getErros()) { + case 2 -> { + message = String.format( + "Percebemos que você teve dificuldade %s, por isso deve voltar e ver mais um exemplo!", + context.equals("Competencia") ? "com essa competência" + : "em identificar a competência nas questões apresentadas"); + module.setEstado(EstadoModulo.EXEMPLOS); + } + case 3 -> { + message = String.format( + "Como você não conseguiu identificar bem %s, veja uma nova competência e depois tentaremos essa novamente!", + context.equals("Competencia") ? "a competência" + : "a presença ou ausência da competência nas questões apresentadas"); + module.resetarErros(); + module.setEstado(EstadoModulo.DESCRICAO); + } + default -> message = String.format("%s, tente novamente!", context.equals("Competencia") ? "Não conseguimos identificar a presença da competência atual no enunciado a presença da competência atual no enunciado" : "Você não conseguiu identificar a presença ou ausência da competência nas questões apresentadas"); @@ -602,22 +575,18 @@ private String validateEvaluationQuestion(Usuario user, Questao question, Modulo * @return Mensagem de feedback para o usuário. */ private String evaluateFinalQuestion(Usuario user, ModuloCurso module) { - String message = null; - try { Questao question = questaoService.getById(module.getQuestoes().get(0)); - if (!question.getAutor().equals(user.getEmail())) { - message = "A questão precisa ser de sua autoria!"; - } else if (question.getEstado() != EstadoQuestao.PUBLICADA) { - message = "Você deve criar uma nova questão para prosseguir!"; - } else { - message = validateEvaluationQuestion(user, question, module); - } + if (!question.getAutor().equals(user.getEmail())) + return "A questão precisa ser de sua autoria!"; + else if (question.getEstado() != EstadoQuestao.PUBLICADA) + return "Você deve criar uma nova questão para prosseguir!"; + else + return validateEvaluationQuestion(user, question, module); + } catch (Exception e) { - message = "Você deve criar uma nova questão para prosseguir!"; + return "Você deve criar uma nova questão para prosseguir!"; } - - return message; } /** @@ -640,7 +609,7 @@ private String evaluateCompetence(Usuario user, List answers, ModuloCurs message = handleErrorModule(module, "Competencia"); } else { module.setEstado(EstadoModulo.FINALIZADO); - module.zeraErros(); + module.resetarErros(); } } catch (Exception e) { message = "Problema interno ao classificar questão, tente novamente!"; diff --git a/backend/src/main/java/springboot/service/EmailService.java b/backend/src/main/java/springboot/service/EmailService.java new file mode 100644 index 00000000..988daabb --- /dev/null +++ b/backend/src/main/java/springboot/service/EmailService.java @@ -0,0 +1,26 @@ +package springboot.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.mail.SimpleMailMessage; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.stereotype.Service; + +import springboot.model.Email; + +@Service +public class EmailService { + + @Autowired + private JavaMailSender emailSender; + + public void sendEmail(Email email) { + SimpleMailMessage message = new SimpleMailMessage(); + message.setTo("aepc.lacina@gmail.com"); + message.setSubject(email.getSubject()); + message.setText("From: ".concat(email.getUsername()).concat("\n").concat(email.getMessage())); + message.setReplyTo(email.getEmail()); + message.setFrom(email.getEmail()); + + emailSender.send(message); + } +} diff --git a/backend/src/main/java/springboot/service/ListaQuestoesService.java b/backend/src/main/java/springboot/service/ListaQuestoesService.java index fc02a9b1..43af5ff8 100644 --- a/backend/src/main/java/springboot/service/ListaQuestoesService.java +++ b/backend/src/main/java/springboot/service/ListaQuestoesService.java @@ -1,9 +1,5 @@ package springboot.service; -import java.util.ArrayList; -import java.util.Optional; - -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; @@ -18,103 +14,58 @@ @Service public class ListaQuestoesService { - - private final String errorMessage = "Lista de Questões não está cadastrada."; - public static final int NOME_LISTA = 0; - - private ArrayList arrayParametros = new ArrayList(); - private ArrayList arrayOperadores = new ArrayList(); - private ArrayList arrayQuery = new ArrayList(); - private ArrayList parametros = new ArrayList(); + private static final String ERROR_MESSAGE = "Lista de Questões não está cadastrada."; - @Autowired - private ListaQuestoesRepository listaQuestoesRepository; + private final ListaQuestoesRepository listaQuestoesRepository; + public ListaQuestoesService(ListaQuestoesRepository listaQuestoesRepository) { + this.listaQuestoesRepository = listaQuestoesRepository; + } public ListaQuestoes save(ListaQuestoes listaQuestoes) { - listaQuestoesRepository.save(listaQuestoes); - return listaQuestoes; + return listaQuestoesRepository.save(listaQuestoes); } - - - public ListaQuestoes update(ListaQuestoes listaQuestoes, String id) { - Optional optListaQuestoes = listaQuestoesRepository.findById(id); - - if (!optListaQuestoes.isPresent()) { - throw new RegisterNotFoundException(errorMessage); - } - ListaQuestoes novaListaQuestoes = optListaQuestoes.get(); + public ListaQuestoes update(ListaQuestoes listaQuestoes, String id) { + ListaQuestoes existingListaQuestoes = findListaQuestoesById(id); - if (!listaQuestoes.getAutor().equals(novaListaQuestoes.getAutor())) { + if (!listaQuestoes.getAutor().equals(existingListaQuestoes.getAutor())) { throw new PermissionDeniedException("A lista é de propriedade de outro usuário"); } - novaListaQuestoes.setNomeLista(listaQuestoes.getNomeLista()); - novaListaQuestoes.setAutor(listaQuestoes.getAutor()); - novaListaQuestoes.setQuestoes(listaQuestoes.getQuestoes()); - - listaQuestoesRepository.save(novaListaQuestoes); + existingListaQuestoes.setNomeLista(listaQuestoes.getNomeLista()); + existingListaQuestoes.setAutor(listaQuestoes.getAutor()); + existingListaQuestoes.setQuestoes(listaQuestoes.getQuestoes()); - return novaListaQuestoes; + return listaQuestoesRepository.save(existingListaQuestoes); } public ListaQuestoes delete(String id) { - Optional optListaQuestoes = listaQuestoesRepository.findById(id); - - if (!optListaQuestoes.isPresent()) { - throw new RegisterNotFoundException(errorMessage); - } - - ListaQuestoes listaQuestoes = optListaQuestoes.get(); + ListaQuestoes listaQuestoes = findListaQuestoesById(id); listaQuestoesRepository.delete(listaQuestoes); - return listaQuestoes; } - - private void iniciaColecoes() { - arrayParametros.add("{$text:{$search:"); - arrayParametros.add("{email:"); - - arrayOperadores.add("{'$or':["); - arrayOperadores.add("{'$and':["); - } - public Page getAll(Usuario usuario, int page, int size) { Pageable pageable = PageRequest.of(page, size); return listaQuestoesRepository.getByAutor(usuario.getEmail(), pageable); } - - - public ListaQuestoes getById(String id) { - Optional optListaQuestoes = listaQuestoesRepository.findById(id); - - if (!optListaQuestoes.isPresent()) { - throw new RegisterNotFoundException(errorMessage); - } - return optListaQuestoes.get(); + public ListaQuestoes getById(String id) { + return findListaQuestoesById(id); } public Page getByUser(Usuario user, int page, int size) { + Sort sort = Sort.by( + Sort.Order.desc("score")); - - // Sort sort = Sort.by( - // Sort.Order.desc("score")); - - Pageable pageable = PageRequest.of(page, size); - - Page pagina = listaQuestoesRepository.getByAutor(user.getEmail(),pageable); - - - return pagina; + Pageable pageable = PageRequest.of(page, size, sort); + return listaQuestoesRepository.getByAutor(user.getEmail(), pageable); } - private boolean isNull(Object parametro) { - return parametro.equals("null"); + private ListaQuestoes findListaQuestoesById(String id) { + return listaQuestoesRepository.findById(id) + .orElseThrow(() -> new RegisterNotFoundException(ERROR_MESSAGE)); } - - } diff --git a/backend/src/main/java/springboot/service/QuestaoService.java b/backend/src/main/java/springboot/service/QuestaoService.java index 0d154740..873e2ee0 100644 --- a/backend/src/main/java/springboot/service/QuestaoService.java +++ b/backend/src/main/java/springboot/service/QuestaoService.java @@ -235,7 +235,6 @@ else if (competencias.contains("COMP_TODAS")) aggList.add(1, new CustomAggregationOperation(Document.parse(query))); - System.out.println(query); parametros.clear(); arrayQuery.clear(); @@ -361,44 +360,49 @@ public Questao getAvaliada() { return results.get(0); } - // Busca duas questões (uma com a competência recebida e outra sem a competência recebida) e as embaralha numa lista public List getSamples(String competencia) { - List aggList1 = new ArrayList<>(); - List aggList2 = new ArrayList<>(); + List aggList1 = new ArrayList<>(); + List aggList2 = new ArrayList<>(); + aggList1.add(new CustomAggregationOperation(Document.parse( - "{\n" + - " $match: {\n" + - " competencias: \"" + competencia + "\",\n" + - " estado: \"PUBLICADA\"\n" + - " }\n" + - "}" - ))); + "{\n" + .concat(" $match: {\n") + .concat(" competencias: \"").concat(competencia).concat("\",\n") + .concat(" estado: \"PUBLICADA\"\n") + .concat(" }\n") + .concat("}")))); + aggList2.add(new CustomAggregationOperation(Document.parse( - "{\n" + - " $match: {\n" + - " competencias: { $ne: \"" + competencia + "\" },\n" + - " estado: \"PUBLICADA\"\n" + - " }\n" + - "}" - ))); + "{\n" + .concat(" $match: {\n") + .concat(" competencias: { $ne: \"").concat(competencia).concat("\" },\n") + .concat(" estado: \"PUBLICADA\"\n") + .concat(" }\n") + .concat("}")))); + aggList1.add(new CustomAggregationOperation(Document.parse("{ $sample: { size: 1 } }"))); aggList2.add(new CustomAggregationOperation(Document.parse("{ $sample: { size: 1 } }"))); + Aggregation agg = Aggregation.newAggregation(aggList1); - List results = new ArrayList(); + List results = new ArrayList<>(); + for (Questao q : mongoTemplate.aggregate(agg, "questao", Questao.class).getMappedResults()) { results.add(q); } + agg = Aggregation.newAggregation(aggList2); + for (Questao q : mongoTemplate.aggregate(agg, "questao", Questao.class).getMappedResults()) { results.add(q); } - //Embaralha a ordem de retrno das questões de exemplo (com ou sem a competência) - Collections.swap(results, 0, new Random().nextInt(2)); + + Collections.swap(results, 0, new Random().nextInt(Math.max(0, results.size()))); return results; } public Questao getSample(String competencia) { - return getSamples(competencia).get(new Random().nextInt(2)); + List samples = getSamples(competencia); + return samples.get(new Random().nextInt(Math.max(0, samples.size()))); } public Boolean hasCompetencia(String competencia, Set competencias) { @@ -415,7 +419,6 @@ public Boolean evaluateQuestao(String competencia, String questao) { return hasCompetencia(competencia, q.getCompetencias()); } - // Retorna lista de booleanos que representa se as questoes passadas como parametro possuem ou não a competência buscada public List evaluateQuestoes(String competencia, List questoes) { List ret = new ArrayList<>(); for (String id : questoes) { @@ -424,8 +427,6 @@ public List evaluateQuestoes(String competencia, List questoes) return ret; } - - public boolean updateClassificador() { List l = questaoRepository.findAll(); for (Questao q : l) { diff --git a/backend/src/main/java/springboot/service/UsuarioPermissaoService.java b/backend/src/main/java/springboot/service/UsuarioPermissaoService.java index 2066647a..7a19a158 100644 --- a/backend/src/main/java/springboot/service/UsuarioPermissaoService.java +++ b/backend/src/main/java/springboot/service/UsuarioPermissaoService.java @@ -1,9 +1,7 @@ package springboot.service; import java.util.List; -import java.util.Optional; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import springboot.exception.data.PermissionDeniedException; @@ -14,50 +12,39 @@ @Service public class UsuarioPermissaoService { - private final String errorMessage = "Usuário ainda não registrado no sistema!"; + private static final String ERROR_MESSAGE = "Usuário ainda não registrado no sistema!"; - @Autowired - private UsuarioPermissaoRepository usuarioPermissaoRepository; + private final UsuarioPermissaoRepository usuarioPermissaoRepository; - public UsuarioPermissao savePermissao(UsuarioPermissao usuarioPermissao) { - usuarioPermissaoRepository.save(usuarioPermissao); - return usuarioPermissao; + public UsuarioPermissaoService(UsuarioPermissaoRepository usuarioPermissaoRepository) { + this.usuarioPermissaoRepository = usuarioPermissaoRepository; } - - public UsuarioPermissao update(UsuarioPermissao usuarioPermissao, String email) { - Optional optUsuario = usuarioPermissaoRepository.findById(email); - if (!optUsuario.isPresent()) { - throw new RegisterNotFoundException(errorMessage); - } + public UsuarioPermissao savePermissao(UsuarioPermissao usuarioPermissao) { + return usuarioPermissaoRepository.save(usuarioPermissao); + } - UsuarioPermissao novoUsuarioPermissao = optUsuario.get(); + public UsuarioPermissao update(UsuarioPermissao usuarioPermissao, String email) { + UsuarioPermissao existingUsuarioPermissao = findUsuarioById(email); - if (!novoUsuarioPermissao.getEmail().equals(email)) { + if (!existingUsuarioPermissao.getEmail().equals(email)) { throw new PermissionDeniedException("A permissão de um usuário só pode ser alterada por ele mesmo."); } - novoUsuarioPermissao.setEmail(usuarioPermissao.getEmail()); - novoUsuarioPermissao.setPermissao(usuarioPermissao.getPermissao()); - - usuarioPermissaoRepository.save(novoUsuarioPermissao); - - return novoUsuarioPermissao; + existingUsuarioPermissao.setPermissao(usuarioPermissao.getPermissao()); + return usuarioPermissaoRepository.save(existingUsuarioPermissao); } - + public List getAll() { return usuarioPermissaoRepository.findAll(); } public UsuarioPermissao getById(String email) { - Optional optUsuario = usuarioPermissaoRepository.findById(email); - - if (!optUsuario.isPresent()) { - throw new RegisterNotFoundException(errorMessage); - } - - return optUsuario.get(); + return findUsuarioById(email); } - + private UsuarioPermissao findUsuarioById(String email) { + return usuarioPermissaoRepository.findById(email) + .orElseThrow(() -> new RegisterNotFoundException(ERROR_MESSAGE)); + } } diff --git a/backend/src/main/java/springboot/service/UsuarioService.java b/backend/src/main/java/springboot/service/UsuarioService.java index 11a12e52..6c11a0a8 100644 --- a/backend/src/main/java/springboot/service/UsuarioService.java +++ b/backend/src/main/java/springboot/service/UsuarioService.java @@ -1,11 +1,8 @@ package springboot.service; import java.util.List; -import java.util.Optional; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; - import springboot.exception.data.RegisterNotFoundException; import springboot.model.Usuario; import springboot.repository.UsuarioRepository; @@ -13,65 +10,67 @@ @Service public class UsuarioService { - private final String errorMessage = "Usuário ainda não registrado no sistema!"; + private static final String ERROR_MESSAGE = "Usuário ainda não registrado no sistema!"; @Autowired private UsuarioRepository usuarioRepository; - public UsuarioService() { - } - + /** + * Salva um novo usuário no banco de dados. + * + * @param usuario O usuário a ser salvo. + * @return O usuário salvo. + */ public Usuario save(Usuario usuario) { - usuarioRepository.save(usuario); - return usuario; + return usuarioRepository.save(usuario); } - + /** + * Deleta um usuário existente pelo e-mail. + * + * @param email O e-mail do usuário a ser deletado. + * @return O usuário deletado. + * @throws RegisterNotFoundException Se o usuário não for encontrado. + */ public Usuario delete(String email) { - Optional optUsuario = usuarioRepository.findById(email); - - if (!optUsuario.isPresent()) { - throw new RegisterNotFoundException(errorMessage); - } + Usuario usuario = usuarioRepository.findById(email) + .orElseThrow(() -> new RegisterNotFoundException(ERROR_MESSAGE)); - Usuario usuario = optUsuario.get(); usuarioRepository.delete(usuario); - return usuario; } + /** + * Atualiza as informações de um usuário existente. + * + * @param novoUsuario O objeto com as novas informações do usuário. + * @param email O e-mail do usuário a ser atualizado. + * @return O usuário atualizado. + * @throws RegisterNotFoundException Se o usuário não for encontrado. + */ public Usuario update(Usuario novoUsuario, String email) { - Optional optUsuario = usuarioRepository.findById(email); - - if (!optUsuario.isPresent()) { - throw new RegisterNotFoundException(errorMessage); - } - - novoUsuario.setEmail(email); - - usuarioRepository.save(novoUsuario); - - return novoUsuario; + usuarioRepository.findById(email).orElseThrow(() -> new RegisterNotFoundException(ERROR_MESSAGE)); + return usuarioRepository.save(novoUsuario); } + /** + * Recupera todos os usuários do banco de dados. + * + * @return A lista de todos os usuários. + */ public List getAll() { return usuarioRepository.findAll(); } + /** + * Recupera um usuário específico pelo e-mail. + * + * @param email O e-mail do usuário a ser recuperado. + * @return O usuário encontrado. + * @throws RegisterNotFoundException Se o usuário não for encontrado. + */ public Usuario getById(String email) { - Optional optUsuario = usuarioRepository.findById(email); - - if (!optUsuario.isPresent()) { - throw new RegisterNotFoundException(errorMessage); - } - - return optUsuario.get(); + return usuarioRepository.findById(email) + .orElseThrow(() -> new RegisterNotFoundException(ERROR_MESSAGE)); } - - - /* - * public Usuario pesquisarPorNome(String nome) { return - * usuarioRepository.pesquisarPorNome(nome); } - */ - } From 4f1717dcfbc101b132b5cea5509b11ec76e04cb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Vitor?= Date: Tue, 17 Sep 2024 02:48:42 -0300 Subject: [PATCH 10/18] docs: utils functions --- .../util/CustomAggregationOperation.java | 33 ++++++++++++++++--- .../springboot/util/GoogleIdVerifier.java | 13 +++++--- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/backend/src/main/java/springboot/util/CustomAggregationOperation.java b/backend/src/main/java/springboot/util/CustomAggregationOperation.java index 49e85a6e..004f7ffb 100644 --- a/backend/src/main/java/springboot/util/CustomAggregationOperation.java +++ b/backend/src/main/java/springboot/util/CustomAggregationOperation.java @@ -1,19 +1,42 @@ package springboot.util; -import com.mongodb.DBObject; import org.bson.Document; import org.springframework.data.mongodb.core.aggregation.AggregationOperation; import org.springframework.data.mongodb.core.aggregation.AggregationOperationContext; +/** + * Classe que permite definir operações de agregação personalizadas para + * consultas MongoDB no contexto do Spring Data. + */ public class CustomAggregationOperation implements AggregationOperation { - private Document operation; - public CustomAggregationOperation (Document operation) { - this.operation = operation; + private final Document aggregationOperationDocument; + + /** + * Construtor que inicializa a operação de agregação com o documento + * especificado. + * + * @param aggregationOperationDocument Documento BSON que representa a operação + * de agregação personalizada. + * @throws IllegalArgumentException se o documento fornecido for nulo. + */ + public CustomAggregationOperation(Document aggregationOperationDocument) { + if (aggregationOperationDocument == null) { + throw new IllegalArgumentException("O documento de operação de agregação não pode ser nulo."); + } + this.aggregationOperationDocument = aggregationOperationDocument; } + /** + * Converte a operação de agregação personalizada em um documento compatível com + * o contexto de agregação do Spring Data. + * + * @param context Contexto de operação de agregação usado para mapear a + * operação. + * @return Documento BSON mapeado para o contexto de agregação. + */ @Override public Document toDocument(AggregationOperationContext context) { - return context.getMappedObject(operation); + return context.getMappedObject(aggregationOperationDocument); } } diff --git a/backend/src/main/java/springboot/util/GoogleIdVerifier.java b/backend/src/main/java/springboot/util/GoogleIdVerifier.java index 44acfccc..c90edcef 100644 --- a/backend/src/main/java/springboot/util/GoogleIdVerifier.java +++ b/backend/src/main/java/springboot/util/GoogleIdVerifier.java @@ -1,21 +1,24 @@ package springboot.util; +import java.io.IOException; +import java.security.GeneralSecurityException; + import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken; import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier; import com.google.api.client.http.javanet.NetHttpTransport; -import com.google.api.client.json.jackson2.JacksonFactory; -import org.springframework.beans.factory.annotation.Autowired; import springboot.exception.auth.InvalidTokenException; import springboot.model.Usuario; import springboot.service.UsuarioService; import java.util.Collections; +import com.google.api.client.json.gson.GsonFactory; + public class GoogleIdVerifier { static final String CLIENT_ID = "1024214029990-d9ppvf55b3sv7ias7b7uhltclj9b1j2g.apps.googleusercontent.com"; - static final GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(new NetHttpTransport(), JacksonFactory.getDefaultInstance()) + static final GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(new NetHttpTransport(), GsonFactory.getDefaultInstance()) .setAudience(Collections.singletonList(CLIENT_ID)).build(); public static GoogleIdToken.Payload getPayload(String tokenString) { @@ -26,7 +29,7 @@ public static GoogleIdToken.Payload getPayload(String tokenString) { } else { throw new InvalidTokenException(); } - } catch (Exception e) { + } catch (IOException | GeneralSecurityException | InvalidTokenException e) { throw new InvalidTokenException(); } } @@ -44,7 +47,7 @@ public static Usuario getUsuario(String tokenString, UsuarioService service) { } else { throw new InvalidTokenException(); } - } catch (Exception e) { + } catch (IOException | GeneralSecurityException | InvalidTokenException e) { throw new InvalidTokenException(); } } From 0eeb20d8c8a3ab68e1e245f64d4cd9a0489f623b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Vitor?= Date: Tue, 17 Sep 2024 02:49:56 -0300 Subject: [PATCH 11/18] refactory: controllers failed --- frontend/app/controllers/BuscasController.js | 2 +- frontend/app/controllers/CursosController.js | 6 +++--- frontend/app/controllers/MeusDadosController.js | 4 ++-- frontend/app/controllers/SignUpController.js | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/frontend/app/controllers/BuscasController.js b/frontend/app/controllers/BuscasController.js index 5b0fd41e..ba6c5370 100644 --- a/frontend/app/controllers/BuscasController.js +++ b/frontend/app/controllers/BuscasController.js @@ -554,7 +554,7 @@ angular.module('app') observacaoAvaliacao: $rootScope.avaliacao.obsAvaliacao, observacaoQuestao: $rootScope.avaliacao.obsQuestao, avaliacaoPublicacao: $rootScope.avaliacao.avaliacaoPublicacao, - questao: $rootScope.questaoSobAvaliacao.id, + questaoId: $rootScope.questaoSobAvaliacao.id, competencias: arr, infoCompetencias: arr2, confianca: $rootScope.avaliacao.confianca diff --git a/frontend/app/controllers/CursosController.js b/frontend/app/controllers/CursosController.js index 7b57bed7..d7c4e357 100644 --- a/frontend/app/controllers/CursosController.js +++ b/frontend/app/controllers/CursosController.js @@ -217,7 +217,7 @@ angular.module('app') $scope.nextStepAvaliacao = () => { if ($scope.estadoAtual.modulo === $scope.progressoAvaliacao.modulo && $scope.estadoAtual.estado === $scope.progressoAvaliacao.estado) { $rootScope.loading = true; - $http.post(host + 'cursoAvaliacao/', $scope.progressoAvaliacao.respostas, AuthService.getAuthorization()).then( + $http.post(host + 'cursoAvaliacao', $scope.progressoAvaliacao.respostas, AuthService.getAuthorization()).then( response => { $rootScope.loading = false; if (response.data.mensagem) { @@ -322,7 +322,7 @@ angular.module('app') $scope.nextStepCriacao = () => { if ($scope.estadoAtual.modulo === $scope.progressoCriacao.modulo && $scope.estadoAtual.estado === $scope.progressoCriacao.estado) { $rootScope.loading = true; - $http.post(host + 'cursoCriacao/', $scope.progressoCriacao.respostas, AuthService.getAuthorization()).then( + $http.post(host + 'cursoCriacao', $scope.progressoCriacao.respostas, AuthService.getAuthorization()).then( response => { $rootScope.loading = false; if (response.data.mensagem) { @@ -390,7 +390,7 @@ angular.module('app') } $scope.getCursos = () => { - $http.get(host + 'cursos/', AuthService.getAuthorization()).then( + $http.get(host + 'cursos', AuthService.getAuthorization()).then( response => { $scope.populaDadosAvaliacao(response.data.cursoAvaliacao, false, true); $scope.populaDadosCriacao(response.data.cursoCriacao, false, true); diff --git a/frontend/app/controllers/MeusDadosController.js b/frontend/app/controllers/MeusDadosController.js index 33943c47..35e9b5f6 100644 --- a/frontend/app/controllers/MeusDadosController.js +++ b/frontend/app/controllers/MeusDadosController.js @@ -15,7 +15,7 @@ angular.module('app') $rootScope.loading = true; - $http.get(host + 'usuario/', AuthService.getAuthorization()). + $http.get(host + 'usuario', AuthService.getAuthorization()). then(function (response) { console.log($rootScope.loading); @@ -39,7 +39,7 @@ angular.module('app') nomeInstituicao: $scope.instituicao_usuario }; - $http.put(host + 'usuario/', user, AuthService.getAuthorization()). + $http.put(host + 'usuario', user, AuthService.getAuthorization()). then(function (response) { Notification.success("Usuario atualizado com Sucesso!"); }, function (err){ diff --git a/frontend/app/controllers/SignUpController.js b/frontend/app/controllers/SignUpController.js index e977b022..27b03969 100644 --- a/frontend/app/controllers/SignUpController.js +++ b/frontend/app/controllers/SignUpController.js @@ -14,7 +14,7 @@ angular.module('app') nomeInstituicao: $scope.nomeInstituicao }; - $http.post(host + 'auth/signup/', usuario, AuthService.getAuthorization()). + $http.post(host + 'auth/signup', usuario, AuthService.getAuthorization()). then(function () { Notification.success("Cadastro efetuado com Sucesso!"); $rootScope.registered = true; From 8be6a90996af9f5fbae1f8269342836d85ce3c2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Vitor?= Date: Tue, 17 Sep 2024 02:50:44 -0300 Subject: [PATCH 12/18] fix: controller files (frontend) --- frontend/app/services/AuthService.js | 4 +-- frontend/app/services/QuestoesService.js | 37 +++++++++++++++--------- frontend/app/services/UserService.js | 2 +- 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/frontend/app/services/AuthService.js b/frontend/app/services/AuthService.js index dda78205..cb824a7a 100644 --- a/frontend/app/services/AuthService.js +++ b/frontend/app/services/AuthService.js @@ -42,10 +42,10 @@ angular.module('app') $location.path("/login"); return; } - $http.get(host + 'auth/authenticate/', service.getAuthorization()) + $http.get(host + 'auth/authenticate', service.getAuthorization()) .then(function () { $rootScope.registered = true; - $http.get(host + 'usuario/', service.getAuthorization()). + $http.get(host + 'usuario', service.getAuthorization()). then(function (response) { $rootScope.instituicao_usuario = response.data.nomeInstituicao, diff --git a/frontend/app/services/QuestoesService.js b/frontend/app/services/QuestoesService.js index f79bedd9..3f250da3 100644 --- a/frontend/app/services/QuestoesService.js +++ b/frontend/app/services/QuestoesService.js @@ -24,32 +24,43 @@ angular.module('app') }, - service.sendQuery = function (query, pageNumber, usersPerPage, apenasAutor) { - let estados = query.estados.length === 0 ? ' ' : query.estados.join(","); - let competencias = query.competencias.length === 0 ? ' ' : query.competencias.join(","); - let conteudo = query.conteudo.length === 0 ? ' ' : query.conteudo.join(","); - return $http.get(host + 'questao/' + ((apenasAutor) ? 'searchMy/' : 'search/') + query.enunciado + '/' + competencias + '/' + ((apenasAutor) ? estados + '/' : '') - + ((apenasAutor) ? '' : query.autor + '/') + query.fonte + '/' + query.tipo + '/' + conteudo + '/' + pageNumber + '/' + usersPerPage, AuthService.getAuthorization()). - then(function (response) { +service.sendQuery = function (query, pageNumber, usersPerPage, apenasAutor) { + let estados = query.estados.length === 0 ? '' : query.estados.join(","); + let competencias = query.competencias.length === 0 ? '' : query.competencias.join(","); + let conteudo = query.conteudo.length === 0 ? '' : query.conteudo.join(","); + console.log(apenasAutor) + + // Construção da URL com parâmetros query (em vez de path parameters) + let url = host + (apenasAutor ? 'questao/searchMy?' : 'questao/search?') + + 'enunciado=' + encodeURIComponent(query.enunciado || 'null') + + '&competencias=' + encodeURIComponent(competencias) + + (apenasAutor ? '&estados=' + encodeURIComponent(estados) : '') + + '&autor=' + encodeURIComponent(apenasAutor ? '' : query.autor || 'null') + + '&fonte=' + encodeURIComponent(query.fonte || 'null') + + '&tipo=' + encodeURIComponent(query.tipo || 'null') + + '&conteudo=' + encodeURIComponent(conteudo) + + '&page=' + pageNumber + + '&size=' + usersPerPage; + + return $http.get(url, AuthService.getAuthorization()) + .then(function (response) { $rootScope.Questoes = response.data.content; $rootScope.totalQuestoes = response.data.totalElements; $rootScope.pageNumber = response.data.number; $rootScope.totalPags = response.data.totalPages; $rootScope.loading = false; - if (query.enunciado !== "") $rootScope.adicionaMarcadores(query.enunciado); - return response; - }, function (err) { if (err.status == 400) { $rootScope.forceSignOut(); } return err; }); - }, +}; + @@ -248,7 +259,7 @@ service.getCompetencias = function (enunciado) { } service.getQuestaoPendente = function() { - return $http.get(host + 'questao/pendente/', AuthService.getAuthorization()) + return $http.get(host + 'questao/pendente', AuthService.getAuthorization()) .then(function(response) { $rootScope.questaoSobAvaliacao = response.data; $rootScope.questaoSobAvaliacao.enunciado = $sce.trustAsHtml($rootScope.questaoSobAvaliacao.enunciado); @@ -264,7 +275,7 @@ service.getQuestaoPendente = function() { } service.getQuestaoAvaliada = function() { - return $http.get(host + 'questao/avaliada/', AuthService.getAuthorization()) + return $http.get(host + 'questao/avaliada', AuthService.getAuthorization()) .then(function(response) { return response; }, function(err) { diff --git a/frontend/app/services/UserService.js b/frontend/app/services/UserService.js index c225eb58..97b0f9be 100644 --- a/frontend/app/services/UserService.js +++ b/frontend/app/services/UserService.js @@ -5,7 +5,7 @@ angular.module('app') let deferred = $q.defer(); service.isRegistered = function () { - $http.get(host + 'usuario/' + AuthService.getUserDetails().Email). + $http.get(host + 'usuario' + AuthService.getUserDetails().Email). then(function (response) { deferred.resolve(response.status == 200); },function(response){ From 1547ca5e8ccc04591d25eb5a2a9642dba9b1afad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Vitor?= Date: Tue, 24 Sep 2024 21:32:39 -0300 Subject: [PATCH 13/18] removing setScore --- .../src/main/java/springboot/enums/CompetenciaType.java | 9 +++------ .../src/main/java/springboot/model/ListaQuestoes.java | 4 ---- backend/src/main/java/springboot/model/Questao.java | 4 ---- 3 files changed, 3 insertions(+), 14 deletions(-) diff --git a/backend/src/main/java/springboot/enums/CompetenciaType.java b/backend/src/main/java/springboot/enums/CompetenciaType.java index ef939573..6c63ec8f 100644 --- a/backend/src/main/java/springboot/enums/CompetenciaType.java +++ b/backend/src/main/java/springboot/enums/CompetenciaType.java @@ -10,14 +10,11 @@ public enum CompetenciaType { COMP_SIMULAÇÃO("simulation"), COMP_AUTOMAÇÃO("automation"), COMP_ALGORITMOS("algorithms"); - - + public final String value; CompetenciaType(final String value) { - this.value = value; - } - + this.value = value; + } - } diff --git a/backend/src/main/java/springboot/model/ListaQuestoes.java b/backend/src/main/java/springboot/model/ListaQuestoes.java index 5dd618d5..afb78c62 100644 --- a/backend/src/main/java/springboot/model/ListaQuestoes.java +++ b/backend/src/main/java/springboot/model/ListaQuestoes.java @@ -88,8 +88,4 @@ public void setQuestoes(List questoes) { public Float getScore() { return score; } - - public void setScore(Float score) { - this.score = score; - } } diff --git a/backend/src/main/java/springboot/model/Questao.java b/backend/src/main/java/springboot/model/Questao.java index 5870e3a6..16a765cf 100644 --- a/backend/src/main/java/springboot/model/Questao.java +++ b/backend/src/main/java/springboot/model/Questao.java @@ -179,10 +179,6 @@ public Float getScore() { return score; } - public void setScore(Float score) { - this.score = score; - } - public Integer getQtdAvaliacoes() { return qtdAvaliacoes; } From 1eaa64eb4ad20e5ddf2c673f408c499e6bde0863 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Vitor?= Date: Tue, 24 Sep 2024 23:56:40 -0300 Subject: [PATCH 14/18] adding docs --- README.md | 134 +++++++++++++++++++-------- docs/images/architecture-diagram.png | Bin 0 -> 155436 bytes docs/images/use-case-diagram.png | Bin 0 -> 195465 bytes docs/requirements.md | 21 +++++ 4 files changed, 115 insertions(+), 40 deletions(-) create mode 100644 docs/images/architecture-diagram.png create mode 100644 docs/images/use-case-diagram.png create mode 100644 docs/requirements.md diff --git a/README.md b/README.md index d55a8bb2..6286d188 100644 --- a/README.md +++ b/README.md @@ -1,72 +1,126 @@ -# Ambiente de Estudo ao Pensamento Computacional 1.0 +# 🌟 ComPensar -## Iniciando +**Ambiente de Estudo ao Pensamento Computacional 1.1** -Essas instruções vão ajudar você a utilizar o projeto e rodar em sua máquina local para desenvolvimento e testes. +**ComPensar** é uma plataforma voltada para auxiliar o ensino de **Pensamento Computacional (PC)** no contexto da educação básica, com foco na resolução de problemas matemáticos. O sistema oferece ferramentas que permitem a criação, avaliação e publicação de questões alinhadas com as competências do PC, promovendo o desenvolvimento do raciocínio lógico e da capacidade de abstração dos alunos. -### Pré-Requisitos +O Pensamento Computacional é uma habilidade fundamental na educação moderna, pois facilita a aplicação de técnicas e conceitos computacionais para resolver problemas de diversas áreas, incluindo a matemática. Através do ComPensar, educadores podem avaliar o progresso dos alunos em competências essenciais como a decomposição de problemas, reconhecimento de padrões, abstração e criação de algoritmos. -É necessário que você execute os comandos contidos no seguinte arquivo para utilizar um banco de dados MongoDB. Pode ser utilizado ainda uma interface MongoDB, como o Robo3T, para melhor interação com os dados. +## ⚙️ Tecnologias utilizadas -``` -aepc/backend/src/main/resources/import.sql -``` +| Tecnologia | Versão | +| --------------------------------- | ------- | +| [Node.js](https://nodejs.org/en/) | v22.2.0 | +| [Java](https://www.java.com/) | v21 | +| Spring Boot | v3.3.3 | +| MongoDB | v7.0.2 | -### Executar -Para executar o projeto execute como JavaApplication a seguinte classe: +## 🚀 Como levantar o projeto? -``` -aepc/backend/src/main/java/springboot/AepcApplication.java -``` +- **Clone o repositório:** -## Testando a Aplicação + ```bash + git clone https://github.com/ufcg-lsd/compensar-legacy.git + ``` -### Segurança +### Frontend -A segurança nos endpoints está implemetada utilizando HTTP Basic e busca dos usuários no banco de dados utilizando o serviço que implementa UserDetailsService, do Spring Security. Cada usuário possui uma determinada permissão. +1. **Instale as dependências:** -Usuários para testes pré-defindos com um tipo de permissão se encontram também no seguinte arquivo: + ```bash + cd frontend + npm install + ``` -``` -aepc/backend/src/main/resources/import.sql -``` +2. **Execute a aplicação:** -Obs.: Há endpoints específicos para criação de um usuário, e de adição de uma permissão a um usuário (Mais a frente) + ```bash + npm start + ``` +### Backend -Para login e acesso aos endpoints, é utilizado o email e senha de três digitos. No mesmo arquivo se encontram a inserção de alguns usuários exemplo. +1. **Instale as dependências:** + ```bash + cd backend + mvn clean install # Se os testes falharem e você queira rodar assim mesmo, adicione a flag -DskipTests + ``` -### API REST -Para obter uma visualização interativa da API com os endpoints acesse, localmente, o seguinte endereço: +2. **Execute a aplicação:** -``` -http://localhost:8080/swagger-ui.html -``` + ```bash + mvn spring-boot:run + ``` -É possível realizar requisições para testar os endpoints utilizando a interação citada acima, se preferir, existem outras ferramentas (Ex.: Postman). +## 🛠️ Arquitetura -### Endpoint Base +Abaixo está o diagrama da arquitetura geral da aplicação: -``` -http://localhost:8080/api/... -``` +![Diagrama de Arquitetura](./docs/images/architecture-diagram.png) -### Testes de Unidade +### Diagrama de Caso de Uso -Para execução dos testes de unidade execute como JunitTest o seguinte pacote: +O diagrama de caso de uso ilustra as interações entre os usuários e o sistema: +![Diagrama de Caso de Uso](./docs/images/use-case-diagram.png) + +### 📚 Documentação Adicional + +Para mais detalhes sobre a aplicação, como a listagem completa dos requisitos funcionais e não funcionais, acesse a pasta [**/docs**](./docs). Você pode explorar os seguintes conteúdos: + +- [Listagem de Requisitos](./docs/requirements.md) + + + + +## 🏗️ Estrutura de pastas + +```plaintext +├── frontend # Diretório contendo o projeto AngularJS (Está pra ser reescrito em Next.JS em outro repositório) +├── backend # Diretório contendo o projeto Spring ``` -aepc/backend/src/test/java/springboot/aepcinitializr -``` -## Construído Com + +## Variáveis que possivelmente precisarão de modificação +- URI do mongodb: +`spring.data.mongodb.uri` em `backend/src/main/resources/application-.properties` +> P: "Mas eu substituo pelo quê?" +> +> R: Se por algum motivo não conseguir acesso ao BD, colocar o uri do (novo) banco de dados que queira apontar. +- Google Sign-In Client ID: + - backend: `CLIENT_ID` na classe `GoogleIdVerifier` + - frontend: +> P: "Mas eu substituo pelo quê?" +> +> R: Se por algum motivo a autenticação não funcionar, talvez as credenciais estejam vencidas ou inacessíveis por algum motivo. Nesse caso, criar novas usando o Google Cloud e substituir. \ No newline at end of file diff --git a/docs/images/architecture-diagram.png b/docs/images/architecture-diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..1d9ac84c1dd88f25f14c0d7e788f6e4d5473d64a GIT binary patch literal 155436 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 literal 0 HcmV?d00001 diff --git a/docs/images/use-case-diagram.png b/docs/images/use-case-diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..fc134b2ce7047df20c7387659c973e5f9e8c107e GIT binary patch literal 195465 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 up(~2@{H<>r^FEU478C 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 O3^f%k<*G;K;r|N+9WP!0 literal 0 HcmV?d00001 diff --git a/docs/requirements.md b/docs/requirements.md new file mode 100644 index 00000000..81379006 --- /dev/null +++ b/docs/requirements.md @@ -0,0 +1,21 @@ +| **Requisito** | **Descrição** | +| ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **RF1** | O sistema deve disponibilizar uma tela de login integrado com o Google, e esse login deve ser mantido por um longo período de tempo, permitindo que o usuário possa usufruir das suas permissões nesse período de tempo. | +| **RF2** | No seu primeiro acesso à plataforma, o usuário deve ser direcionado a uma página de preenchimento dos seus dados, não podendo utilizar o sistema antes de finalizar este passo. | +| **RF3** | Na página inicial, deve existir um formulário para que o usuário entre em contato com o suporte do Compensar, enviando uma mensagem diretamente para o e-mail oficial do sistema. | +| **RF4** | O sistema deve disponibilizar duas listagens de questões, uma referente às questões já publicadas no sistema e outra referente às questões criadas pelo autor, independente do seu estado dentro do sistema. Essas listagens devem contar com um sistema de filtros por autor, conteúdo, enunciado, fonte, objetiva/subjetiva e competências do PC presentes nas questões. | +| **RF5** | O sistema deve disponibilizar uma opção para que os usuários visualizem informações mais detalhadas sobre determinada questão, e ainda mais detalhamento caso o usuário seja o próprio autor da questão. | +| **RF6** | O sistema deve disponibilizar uma opção para a adição de novas questões para o usuário atual. | +| **RF7** | O sistema deve permitir a edição de questões criadas pelo usuário atual, desde que as mesmas não tenham sido enviadas para publicação. | +| **RF8** | O sistema deve permitir a remoção de questões criadas pelo usuário atual, desde que as mesmas não tenham sido enviadas para publicação. | +| **RF9** | O sistema deve forçar uma rodada de avaliação por 3 pessoas para cada questão antes que a mesma seja publicada. A primeira dessas avaliações é feita pelo próprio autor quando a questão é criada. | +| **RF10** | O sistema deve permitir que usuários com permissão de moderador, tendo posse de informações referentes a certa questão submetida para publicação, possa publicá-la (podendo ser feitas alterações mínimas na questão) ou rejeitá-la. | +| **RF11** | O sistema deve disponibilizar uma listagem de todas as listas de questões cadastradas pelo usuário e uma listagem das questões presentes em cada lista. | +| **RF12** | O sistema deve disponibilizar uma opção para a adição de novas listas de questões para o usuário atual. | +| **RF13** | O sistema deve permitir a edição de listas de questões criadas pelo usuário atual. | +| **RF14** | O sistema deve permitir a remoção de listas de questões criadas pelo usuário atual. | +| **RF15** | O sistema deve disponibilizar a impressão das listas de questões em formato que possa ser utilizado em sala de aula, assim como também devem disponibilizar a impressão da folha de respostas referente à lista. | +| **RF16** | O sistema deve disponibilizar um curso que aborde os princípios da avaliação de novas questões com relação às competências do PC. | +| **RF17** | O sistema deve disponibilizar um curso que aborde os princípios da criação de novas questões com relação às competências do PC. | +| **RNF1** | O sistema deve ser compatível com os navegadores Chrome e Firefox. | +| **RNF2** | Tempo para que a página esteja totalmente carregada deve ser inferior a 5 segundos utilizando como base a métrica do WebPageTest. | From ff16a846dc5aa3624499d33ffba3bdd408ff370a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Vitor?= <34198932+joaovitorsl@users.noreply.github.com> Date: Tue, 24 Sep 2024 23:57:38 -0300 Subject: [PATCH 15/18] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6286d188..341ff6ba 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# 🌟 ComPensar +# 📚 ComPensar **Ambiente de Estudo ao Pensamento Computacional 1.1** @@ -123,4 +123,4 @@ Este projeto está sob a licença [MIT](LICENSE). > P: "Mas eu substituo pelo quê?" > -> R: Se por algum motivo a autenticação não funcionar, talvez as credenciais estejam vencidas ou inacessíveis por algum motivo. Nesse caso, criar novas usando o Google Cloud e substituir. \ No newline at end of file +> R: Se por algum motivo a autenticação não funcionar, talvez as credenciais estejam vencidas ou inacessíveis por algum motivo. Nesse caso, criar novas usando o Google Cloud e substituir. From fdf808dc5bf8293a9ea3eb3d42adcf7246be22a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Vitor?= <34198932+joaovitorsl@users.noreply.github.com> Date: Wed, 25 Sep 2024 00:01:13 -0300 Subject: [PATCH 16/18] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 341ff6ba..a7896f49 100644 --- a/README.md +++ b/README.md @@ -119,7 +119,9 @@ Este projeto está sob a licença [MIT](LICENSE). - Google Sign-In Client ID: - backend: `CLIENT_ID` na classe `GoogleIdVerifier` - - frontend: + - frontend: frontend > index.html em dois lugares + - `` + - `
    ` > P: "Mas eu substituo pelo quê?" > From d35b840cd30763637c9662ce9e81ae5169f24f37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Vitor?= Date: Wed, 25 Sep 2024 00:32:05 -0300 Subject: [PATCH 17/18] javadoc part ii --- .../java/springboot/config/TokenFilter.java | 23 +++++++++++-- .../springboot/controller/AuthController.java | 33 +++++++++++++++++++ .../controller/AvaliacaoController.java | 25 ++++++++++++++ .../controller/EmailController.java | 13 ++++++++ 4 files changed, 92 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/springboot/config/TokenFilter.java b/backend/src/main/java/springboot/config/TokenFilter.java index 884f32ec..99bec7dd 100644 --- a/backend/src/main/java/springboot/config/TokenFilter.java +++ b/backend/src/main/java/springboot/config/TokenFilter.java @@ -21,11 +21,30 @@ import springboot.service.UsuarioService; import springboot.util.GoogleIdVerifier; +/** + * Filtro de autenticação que intercepta requisições HTTP e verifica a + * validade de um token JWT fornecido no cabeçalho da requisição. + * Se o token for válido e o usuário estiver registrado no sistema, + * a requisição é encaminhada para o próximo filtro da cadeia. Caso contrário, + * uma resposta de erro é enviada. + */ public class TokenFilter extends GenericFilterBean { @Autowired private UsuarioService usuarioService; + /** + * Intercepta requisições HTTP, validando o token JWT no cabeçalho da + * requisição. + * Se o token for válido e o usuário registrado, a requisição é encaminhada. + * + * @param request a requisição HTTP + * @param response a resposta HTTP + * @param chain a cadeia de filtros + * @throws IOException se ocorrer um erro durante o processamento do token + * ou da requisição + * @throws ServletException se ocorrer um erro durante o processamento do filtro + */ @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { @@ -79,7 +98,7 @@ private String extractToken(HttpServletRequest request) { * @param token o token JWT a ser validado * @param response a resposta HTTP para enviar erros, se necessário * @return o payload do token se for válido, ou null caso contrário - * @throws IOException + * @throws IOException se ocorrer um erro durante a validação do token */ private GoogleIdToken.Payload validateToken(String token, HttpServletResponse response) throws IOException { try { @@ -111,7 +130,7 @@ private boolean isTokenExpired(GoogleIdToken.Payload payload) { * @param email o e-mail do usuário * @param response a resposta HTTP para enviar erros, se necessário * @return true se o usuário estiver registrado, false caso contrário - * @throws IOException + * @throws IOException se ocorrer um erro durante a verificação do usuário */ private boolean isUserRegistered(String email, HttpServletResponse response) throws IOException { try { diff --git a/backend/src/main/java/springboot/controller/AuthController.java b/backend/src/main/java/springboot/controller/AuthController.java index e78d06d0..0e1a7772 100644 --- a/backend/src/main/java/springboot/controller/AuthController.java +++ b/backend/src/main/java/springboot/controller/AuthController.java @@ -26,6 +26,12 @@ import springboot.service.UsuarioService; import springboot.util.GoogleIdVerifier; +/** + * Controlador responsável por gerenciar as operações de autenticação e cadastro de usuários. + * + * Utiliza a API do Google para verificar tokens e validações antes de permitir que + * um usuário seja autenticado ou registrado no sistema. + */ @RestController @RequestMapping("/api") @CrossOrigin(origins = "*") @@ -35,6 +41,11 @@ public class AuthController { @Autowired private UsuarioService usuarioService; + /** + * Autentica um usuário no sistema. + * + * @return uma resposta HTTP contendo uma mensagem de sucesso e a data da autenticação. + */ @Operation(summary = "Permite autenticar um usuário no sistema") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Usuário autenticado com sucesso!") @@ -44,6 +55,16 @@ public ResponseEntity authenticate() { return ResponseEntity.ok(new CustomRestOutput(new Date(), "Usuário autenticado com sucesso!")); } + /** + * Registra um novo usuário no sistema. O token JWT fornecido no cabeçalho da requisição é validado + * para garantir que seja um token legítimo do Google. + * + * @param usuario os dados do usuário a serem cadastrados. + * @param token o token JWT fornecido no cabeçalho "Authorization". + * @return uma resposta HTTP contendo uma mensagem de sucesso e a data do cadastro. + * @throws InvalidTokenException se o token for inválido ou mal formatado. + * @throws UserAlreadyExistException se o usuário já estiver cadastrado no sistema. + */ @Operation(summary = "Permite cadastrar um usuário no sistema") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Usuário cadastrado com sucesso!"), @@ -69,10 +90,22 @@ public ResponseEntity signup(@RequestBody UsuarioInput usuario return ResponseEntity.ok(new CustomRestOutput(new Date(), "Usuário cadastrado com sucesso!")); } + /** + * Extrai o token JWT removendo o prefixo "Bearer ". + * + * @param token o token JWT completo. + * @return o token JWT sem o prefixo. + */ private String extractToken(String token) { return token.substring(7); // Remove "Bearer " } + /** + * Valida o formato do token JWT. O token deve começar com o prefixo "Bearer ". + * + * @param token o token JWT a ser validado. + * @throws InvalidTokenException se o token for nulo ou não começar com "Bearer ". + */ private void validateToken(String token) { if (token == null || !token.startsWith("Bearer ")) { throw new InvalidTokenException(); diff --git a/backend/src/main/java/springboot/controller/AvaliacaoController.java b/backend/src/main/java/springboot/controller/AvaliacaoController.java index dc0eab8d..835cacac 100644 --- a/backend/src/main/java/springboot/controller/AvaliacaoController.java +++ b/backend/src/main/java/springboot/controller/AvaliacaoController.java @@ -31,6 +31,11 @@ import springboot.service.AvaliacaoService; import springboot.service.QuestaoService; +/** + * Controlador responsável por gerenciar operações relacionadas às avaliações no sistema. + * Permite registrar novas avaliações para uma questão específica e atualizar o estado + * da questão com base nas avaliações recebidas. + */ @RestController @RequestMapping(value = "/api") @CrossOrigin(origins = "*") @@ -43,6 +48,18 @@ public class AvaliacaoController { @Autowired private QuestaoService questaoService; + /** + * Registra uma nova avaliação para uma questão específica. A avaliação inclui + * observações, competências avaliadas e informações adicionais. Caso a questão + * atinja três avaliações, o sistema calcula as competências em comum e atualiza + * o estado da questão para "PEND_APROVACAO". + * + * @param usuario o usuário que está realizando a avaliação, obtido a partir de um atributo da requisição. + * @param avaliacao os dados da avaliação, enviados no corpo da requisição. + * @return uma resposta HTTP com a avaliação criada ou com o código de status adequado + * em caso de erro (404 se a questão não for encontrada, 201 para sucesso). + * @throws IOException em caso de erro durante o processamento da avaliação. + */ @Operation(summary = "Permite registrar uma nova avaliação no sistema.") @ApiResponses(value = { @ApiResponse(responseCode = "201", description = "Avaliação criada com sucesso", @@ -84,6 +101,14 @@ public ResponseEntity save(@RequestAttribute(name = "usuario") Usuari return ResponseEntity.status(HttpStatus.CREATED).body(novaAvaliacao); } + /** + * Calcula as competências comuns entre as avaliações de uma determinada questão. + * Para que uma competência seja considerada comum, ela deve estar presente em + * pelo menos duas das três avaliações realizadas. + * + * @param questaoId o ID da questão para a qual as avaliações estão sendo processadas. + * @return um conjunto contendo as competências comuns identificadas entre as avaliações. + */ private HashSet calcularCompetenciasComuns(String questaoId) { List avaliacoes = avaliacaoService.getAllByQuestao(questaoId); HashSet competenciasComuns = new HashSet<>(); diff --git a/backend/src/main/java/springboot/controller/EmailController.java b/backend/src/main/java/springboot/controller/EmailController.java index 159085f7..fc960f59 100644 --- a/backend/src/main/java/springboot/controller/EmailController.java +++ b/backend/src/main/java/springboot/controller/EmailController.java @@ -18,6 +18,10 @@ import springboot.model.Email; import springboot.service.EmailService; +/** + * Controlador responsável pelo envio de emails no sistema. + * Este controlador permite o envio de um email simples de um usuário para o administrador. + */ @RestController @RequestMapping("/api") @CrossOrigin(origins = "*") @@ -27,6 +31,15 @@ public class EmailController { @Autowired private EmailService emailService; + /** + * Envia um email simples de um usuário para o administrador do sistema. + * O email deve ser passado no corpo da requisição, e deve ser validado antes de ser enviado. + * + * @param email objeto contendo as informações do email a ser enviado, validado automaticamente. + * @return uma resposta HTTP indicando o sucesso ou falha do envio. + * - 200 OK se o email foi enviado com sucesso. + * - 500 Internal Server Error se houver um erro ao tentar enviar o email. + */ @Operation(summary = "Permite registrar um email de um user para o admin.") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Email enviado com sucesso"), From ba33a2b5193fa923c410360cbe5b11857c4a2789 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Vitor?= Date: Thu, 26 Sep 2024 01:49:06 -0300 Subject: [PATCH 18/18] fix UsuarioControllerTest --- backend/pom.xml | 5 ++ .../controller/UsuarioController.java | 66 +++++++++++++++++++ .../springboot/service/QuestaoService.java | 3 - .../aepcinitializr/AepcApplicationTests.java | 17 ++--- .../aepcinitializr/UsuarioControllerTest.java | 54 +++++++++------ 5 files changed, 113 insertions(+), 32 deletions(-) diff --git a/backend/pom.xml b/backend/pom.xml index 70bf905e..25289bf0 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -111,6 +111,11 @@ org.mongodb mongodb-driver-core + + junit + junit + test + diff --git a/backend/src/main/java/springboot/controller/UsuarioController.java b/backend/src/main/java/springboot/controller/UsuarioController.java index ad47ecce..89023f93 100644 --- a/backend/src/main/java/springboot/controller/UsuarioController.java +++ b/backend/src/main/java/springboot/controller/UsuarioController.java @@ -5,7 +5,9 @@ import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestAttribute; import org.springframework.web.bind.annotation.RequestBody; @@ -18,6 +20,8 @@ import springboot.model.Usuario; import springboot.service.UsuarioService; +import java.util.List; + @RestController @RequestMapping(value = "/api") @CrossOrigin(origins = "*") @@ -63,4 +67,66 @@ public ResponseEntity update(@RequestAttribute(name = "usuario") Usuari public ResponseEntity getActualUser(@RequestAttribute(name = "usuario") Usuario usuario) { return new ResponseEntity<>(usuario, HttpStatus.OK); } + + /** + * Apaga um usuário do sistema pelo email. + * + * @param email O email do usuário a ser deletado. + * @return O usuário deletado. + */ + @Operation(summary = "Permite apagar um usuário do sistema.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "OK", content = { + @io.swagger.v3.oas.annotations.media.Content(mediaType = MediaType.APPLICATION_JSON_VALUE) }) + }) + @DeleteMapping(value = "/usuario/{email}") + public ResponseEntity delete(@PathVariable("email") String email) { + Usuario usuario = usuarioService.delete(email); + return new ResponseEntity<>(usuario, HttpStatus.OK); + } + + /** + * Retorna todos os usuários registrados. + * + * @return Lista de usuários. + */ + @Operation(summary = "Fornece um array de objetos do tipo usuario registrados.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "OK", content = { + @io.swagger.v3.oas.annotations.media.Content(mediaType = MediaType.APPLICATION_JSON_VALUE) }) + }) + @GetMapping(value = "/usuario/all") + public List getAll() { + return usuarioService.getAll(); + } + + /** + * Recupera um usuário pelo email. + * + * @param email O email do usuário. + * @return O usuário encontrado. + */ + @Operation(summary = "Recupera um usuario com específico email.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "OK", content = { + @io.swagger.v3.oas.annotations.media.Content(mediaType = MediaType.APPLICATION_JSON_VALUE) }) + }) + @GetMapping(value = "/usuario/{email}") + public ResponseEntity getByEmail(@PathVariable("email") String email) { + Usuario usuario = usuarioService.getById(email); + return new ResponseEntity<>(usuario, HttpStatus.OK); + } + + /** + * Pesquisa um usuário pelo nome. + * + * @param nome O nome do usuário. + * @return O usuário encontrado. + */ + // @GetMapping(value = "/usuario/search/{nome}") + // public ResponseEntity searchByNome(@PathVariable("nome") String + // nome) { + // Usuario usuario = usuarioService.pesquisarPorNome(nome); + // return new ResponseEntity<>(usuario, HttpStatus.OK); + // } } diff --git a/backend/src/main/java/springboot/service/QuestaoService.java b/backend/src/main/java/springboot/service/QuestaoService.java index 873e2ee0..b4956951 100644 --- a/backend/src/main/java/springboot/service/QuestaoService.java +++ b/backend/src/main/java/springboot/service/QuestaoService.java @@ -265,9 +265,6 @@ public Set getSetCompetencias(String enunciado) throws IOExcept os.write(enunciadoText.getBytes()); os.flush(); os.close(); - int responseCode = postConnection.getResponseCode(); - - BufferedReader in = new BufferedReader(new InputStreamReader( postConnection.getInputStream())); String inputLine; diff --git a/backend/src/test/java/springboot/aepcinitializr/AepcApplicationTests.java b/backend/src/test/java/springboot/aepcinitializr/AepcApplicationTests.java index 941bce6b..10de33d4 100644 --- a/backend/src/test/java/springboot/aepcinitializr/AepcApplicationTests.java +++ b/backend/src/test/java/springboot/aepcinitializr/AepcApplicationTests.java @@ -1,20 +1,17 @@ package springboot.aepcinitializr; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit4.SpringRunner; +//import org.springframework.test.context.TestPropertySource; import springboot.AepcApplication; -@RunWith(SpringRunner.class) @SpringBootTest(classes = AepcApplication.class) -@TestPropertySource(locations="classpath:test.properties") + public class AepcApplicationTests { - @Test - public void contextLoads() { - } + @Test + public void contextLoads() { + } -} +} \ No newline at end of file diff --git a/backend/src/test/java/springboot/aepcinitializr/UsuarioControllerTest.java b/backend/src/test/java/springboot/aepcinitializr/UsuarioControllerTest.java index 5b46b5af..f2efb95a 100644 --- a/backend/src/test/java/springboot/aepcinitializr/UsuarioControllerTest.java +++ b/backend/src/test/java/springboot/aepcinitializr/UsuarioControllerTest.java @@ -1,7 +1,7 @@ package springboot.aepcinitializr; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; @@ -24,7 +24,7 @@ public class UsuarioControllerTest extends AepcApplicationTests { private Usuario usuario; private Usuario usuarioUpdated; - @Before + @BeforeEach public void setUp() { this.mockMvc = MockMvcBuilders.standaloneSetup(usuarioController).build(); this.usuario = new Usuario("marcelo", 19, "UFCG", "Aluno", "Remígio", "marcelo@gmail.com", true); @@ -33,19 +33,32 @@ public void setUp() { } @Test - public void testGETAllUsuario() throws Exception { - this.mockMvc.perform(MockMvcRequestBuilders.get("/api/usuario")) - .andExpect(MockMvcResultMatchers.status().isOk()); + public void testGETUsuario() throws Exception { + this.mockMvc.perform(MockMvcRequestBuilders.get("/api/usuario") + .requestAttr("usuario", this.usuario) // Simulando o usuário logado + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()); } @Test - public void testPOSTUsuario() throws Exception { - this.mockMvc - .perform(MockMvcRequestBuilders.post("/api/usuario").content(asJsonString(this.usuario)) - .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) - .andExpect(MockMvcResultMatchers.status().isOk()); + public void testGETAllUsuario() throws Exception { + this.mockMvc.perform(MockMvcRequestBuilders.get("/api/usuario/all") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()); } + // TODO: Comentado pois essa função não existe + // @Test + // public void testPOSTUsuario() throws Exception { + // this.mockMvc.perform(MockMvcRequestBuilders.post("/api/usuario") + // .content(asJsonString(this.usuario)) + // .contentType(MediaType.APPLICATION_JSON) + // .accept(MediaType.APPLICATION_JSON) + // .requestAttr("usuario", this.usuario)) // Simulando o usuário logado + // .andExpect(MockMvcResultMatchers.status().isOk()); + // } + + public static String asJsonString(final Object obj) { try { final ObjectMapper mapper = new ObjectMapper(); @@ -56,11 +69,11 @@ public static String asJsonString(final Object obj) { } } - @Test - public void testDELETEUsuario() throws Exception { - this.mockMvc.perform(MockMvcRequestBuilders.delete("/api/usuario/" + this.usuario.getEmail()) - .contentType(MediaType.APPLICATION_JSON)).andExpect(MockMvcResultMatchers.status().isOk()); - } + @Test + public void testDELETEUsuario() throws Exception { + this.mockMvc.perform(MockMvcRequestBuilders.delete("/api/usuario/" + this.usuario.getEmail()) + .contentType(MediaType.APPLICATION_JSON)).andExpect(MockMvcResultMatchers.status().isOk()); + } @Test public void testGETQuestaoUsuarioById() throws Exception { @@ -72,9 +85,12 @@ public void testGETQuestaoUsuarioById() throws Exception { @Test public void testPUTUsuario() throws Exception { - String body = (new ObjectMapper()).valueToTree(usuarioUpdated).toString(); - this.mockMvc.perform(MockMvcRequestBuilders.put("/api/usuario/" + this.usuario.getEmail()).content(body) - .contentType(MediaType.APPLICATION_JSON)).andExpect(MockMvcResultMatchers.status().isOk()); + String body = asJsonString(usuarioUpdated); + this.mockMvc.perform(MockMvcRequestBuilders.put("/api/usuario") + .requestAttr("usuario", this.usuario) + .content(body) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()); } }