Atualização do projeto
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
package com.agendaestudantil;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableScheduling
|
||||
public class AgendaDigitalEstudantesApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(AgendaDigitalEstudantesApplication.class, args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.agendaestudantil.configuracao;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.mongodb.config.EnableMongoAuditing;
|
||||
|
||||
@Configuration
|
||||
@EnableMongoAuditing
|
||||
public class ConfiguracaoMongo {
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.agendaestudantil.configuracao;
|
||||
|
||||
import com.agendaestudantil.filtro.FiltroJwt;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.CorsConfigurationSource;
|
||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
public class ConfiguracaoSeguranca {
|
||||
|
||||
private final FiltroJwt filtroJwt;
|
||||
private final String corsAllowedOrigins;
|
||||
|
||||
public ConfiguracaoSeguranca(FiltroJwt filtroJwt, @Value("${cors.allowed.origins}") String corsAllowedOrigins) {
|
||||
this.filtroJwt = filtroJwt;
|
||||
this.corsAllowedOrigins = corsAllowedOrigins;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
http.csrf(csrf -> csrf.disable())
|
||||
.cors(cors -> cors.configurationSource(corsConfigurationSource()))
|
||||
.authorizeHttpRequests(auth -> auth
|
||||
.requestMatchers(
|
||||
"/", "/index.html", "/login.html", "/cadastro.html", "/calendario.html", "/configuracoes.html",
|
||||
"/favicon.ico", "/imagens/**",
|
||||
"/*.css", "/*.js", "/*.ico", "/*.png",
|
||||
"/api/estudantes/cadastro", "/api/estudantes/login",
|
||||
"/swagger-ui/**", "/v3/api-docs/**")
|
||||
.permitAll()
|
||||
.anyRequest().authenticated())
|
||||
.sessionManagement(session -> session
|
||||
.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
|
||||
.addFilterBefore(filtroJwt, UsernamePasswordAuthenticationFilter.class);
|
||||
|
||||
return http.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CorsConfigurationSource corsConfigurationSource() {
|
||||
CorsConfiguration configuration = new CorsConfiguration();
|
||||
configuration.setAllowedOrigins(List.of(corsAllowedOrigins.split(",")));
|
||||
configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"));
|
||||
configuration.setAllowedHeaders(List.of("*"));
|
||||
configuration.setExposedHeaders(List.of("Authorization"));
|
||||
configuration.setAllowCredentials(true);
|
||||
configuration.setMaxAge(3600L);
|
||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||
source.registerCorsConfiguration("/**", configuration);
|
||||
return source;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PasswordEncoder passwordEncoder() {
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
|
||||
return config.getAuthenticationManager();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.agendaestudantil.configuracao;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
||||
@Controller
|
||||
public class ResourceController {
|
||||
|
||||
@GetMapping("/")
|
||||
public String index() {
|
||||
return "forward:/login.html";
|
||||
}
|
||||
|
||||
@GetMapping("/app")
|
||||
public String app() {
|
||||
return "forward:/calendario.html";
|
||||
}
|
||||
|
||||
@GetMapping("/config")
|
||||
public String config() {
|
||||
return "forward:/configuracoes.html";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package com.agendaestudantil.controlador;
|
||||
|
||||
import com.agendaestudantil.dto.RequisicaoDisciplinaDTO;
|
||||
import com.agendaestudantil.dto.RespostaApi;
|
||||
import com.agendaestudantil.dto.RespostaDisciplinaDTO;
|
||||
import com.agendaestudantil.entidade.Disciplina;
|
||||
import com.agendaestudantil.servico.DisciplinaServico;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/disciplinas")
|
||||
public class DisciplinaControlador {
|
||||
|
||||
private final DisciplinaServico disciplinaServico;
|
||||
|
||||
public DisciplinaControlador(DisciplinaServico disciplinaServico) {
|
||||
this.disciplinaServico = disciplinaServico;
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public ResponseEntity<RespostaApi<RespostaDisciplinaDTO>> criarDisciplina(
|
||||
@Valid @RequestBody RequisicaoDisciplinaDTO dto,
|
||||
@AuthenticationPrincipal UserDetails userDetails) {
|
||||
String estudanteId = userDetails.getUsername();
|
||||
Disciplina disciplina = new Disciplina();
|
||||
disciplina.setNome(dto.nome());
|
||||
disciplina.setProfessor(dto.professor());
|
||||
disciplina.setSala(dto.sala());
|
||||
disciplina.setCor(dto.cor());
|
||||
|
||||
RespostaDisciplinaDTO resposta = disciplinaServico.criarDisciplina(disciplina, estudanteId);
|
||||
return ResponseEntity.status(HttpStatus.CREATED).body(RespostaApi.sucesso(resposta));
|
||||
}
|
||||
|
||||
@GetMapping("/me")
|
||||
public ResponseEntity<RespostaApi<List<RespostaDisciplinaDTO>>> listarPorEstudante(
|
||||
@AuthenticationPrincipal UserDetails userDetails) {
|
||||
String estudanteId = userDetails.getUsername();
|
||||
List<RespostaDisciplinaDTO> disciplinas = disciplinaServico.listarPorEstudante(estudanteId);
|
||||
return ResponseEntity.ok(RespostaApi.sucesso(disciplinas));
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public ResponseEntity<RespostaApi<RespostaDisciplinaDTO>> buscarPorId(
|
||||
@PathVariable String id,
|
||||
@AuthenticationPrincipal UserDetails userDetails) {
|
||||
String estudanteId = userDetails.getUsername();
|
||||
RespostaDisciplinaDTO disciplina = disciplinaServico.buscarPorId(id, estudanteId);
|
||||
return ResponseEntity.ok(RespostaApi.sucesso(disciplina));
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
public ResponseEntity<RespostaApi<RespostaDisciplinaDTO>> atualizarDisciplina(
|
||||
@PathVariable String id,
|
||||
@Valid @RequestBody RequisicaoDisciplinaDTO dto,
|
||||
@AuthenticationPrincipal UserDetails userDetails) {
|
||||
String estudanteId = userDetails.getUsername();
|
||||
Disciplina disciplina = new Disciplina();
|
||||
disciplina.setNome(dto.nome());
|
||||
disciplina.setProfessor(dto.professor());
|
||||
disciplina.setSala(dto.sala());
|
||||
disciplina.setCor(dto.cor());
|
||||
|
||||
RespostaDisciplinaDTO resposta = disciplinaServico.atualizarDisciplina(id, disciplina, estudanteId);
|
||||
return ResponseEntity.ok(RespostaApi.sucesso(resposta));
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
public ResponseEntity<RespostaApi<Void>> excluirDisciplina(
|
||||
@PathVariable String id,
|
||||
@AuthenticationPrincipal UserDetails userDetails) {
|
||||
String estudanteId = userDetails.getUsername();
|
||||
disciplinaServico.excluirDisciplina(id, estudanteId);
|
||||
return ResponseEntity.status(HttpStatus.NO_CONTENT).body(RespostaApi.sucesso(null));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.agendaestudantil.controlador;
|
||||
|
||||
import com.agendaestudantil.dto.RespostaApi;
|
||||
import com.agendaestudantil.dto.RequisicaoAtualizacaoEstudanteDTO;
|
||||
import com.agendaestudantil.dto.RequisicaoCadastroDTO;
|
||||
import com.agendaestudantil.dto.RespostaEstudanteDTO;
|
||||
import com.agendaestudantil.dto.RequisicaoLoginDTO;
|
||||
import com.agendaestudantil.dto.RespostaLoginDTO;
|
||||
import com.agendaestudantil.dto.RequisicaoTrocaSenhaDTO;
|
||||
import com.agendaestudantil.servico.EstudanteServico;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/estudantes")
|
||||
public class EstudanteControlador {
|
||||
|
||||
private final EstudanteServico estudanteServico;
|
||||
|
||||
public EstudanteControlador(EstudanteServico estudanteServico) {
|
||||
this.estudanteServico = estudanteServico;
|
||||
}
|
||||
|
||||
@PostMapping("/cadastro")
|
||||
public ResponseEntity<RespostaApi<RespostaEstudanteDTO>> cadastrar(@Valid @RequestBody RequisicaoCadastroDTO dto) {
|
||||
RespostaEstudanteDTO resposta = estudanteServico.cadastrar(dto);
|
||||
return ResponseEntity.status(HttpStatus.CREATED).body(RespostaApi.sucesso(resposta));
|
||||
}
|
||||
|
||||
@PostMapping("/login")
|
||||
public ResponseEntity<RespostaApi<RespostaLoginDTO>> login(@Valid @RequestBody RequisicaoLoginDTO dto) {
|
||||
RespostaLoginDTO resposta = estudanteServico.login(dto);
|
||||
return ResponseEntity.ok(RespostaApi.sucesso(resposta));
|
||||
}
|
||||
|
||||
// Retorna dados do usuário autenticado via JWT (sem precisar do ID na URL)
|
||||
@GetMapping("/me")
|
||||
public ResponseEntity<RespostaApi<RespostaEstudanteDTO>> me(@AuthenticationPrincipal UserDetails userDetails) {
|
||||
RespostaEstudanteDTO resposta = estudanteServico.buscarPorId(userDetails.getUsername());
|
||||
return ResponseEntity.ok(RespostaApi.sucesso(resposta));
|
||||
}
|
||||
|
||||
// Atualiza dados do usuário autenticado
|
||||
@PutMapping("/me")
|
||||
public ResponseEntity<RespostaApi<RespostaEstudanteDTO>> atualizar(
|
||||
@AuthenticationPrincipal UserDetails userDetails,
|
||||
@Valid @RequestBody RequisicaoAtualizacaoEstudanteDTO dto) {
|
||||
RespostaEstudanteDTO resposta = estudanteServico.atualizar(userDetails.getUsername(), dto);
|
||||
return ResponseEntity.ok(RespostaApi.sucesso(resposta));
|
||||
}
|
||||
|
||||
// Altera senha do usuário autenticado
|
||||
@PutMapping("/senha")
|
||||
public ResponseEntity<RespostaApi<Void>> trocarSenha(
|
||||
@AuthenticationPrincipal UserDetails userDetails,
|
||||
@Valid @RequestBody RequisicaoTrocaSenhaDTO dto) {
|
||||
estudanteServico.trocarSenha(userDetails.getUsername(), dto);
|
||||
return ResponseEntity.ok(RespostaApi.sucesso(null));
|
||||
}
|
||||
|
||||
// Excluir conta do usuário autenticado
|
||||
@DeleteMapping("/me")
|
||||
public ResponseEntity<RespostaApi<Void>> excluirConta(@AuthenticationPrincipal UserDetails userDetails) {
|
||||
estudanteServico.excluirConta(userDetails.getUsername());
|
||||
return ResponseEntity.ok(RespostaApi.sucesso(null));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package com.agendaestudantil.controlador;
|
||||
|
||||
import com.agendaestudantil.dto.RequisicaoEventoDTO;
|
||||
import com.agendaestudantil.dto.RespostaApi;
|
||||
import com.agendaestudantil.dto.RespostaEventoDTO;
|
||||
import com.agendaestudantil.entidade.Evento;
|
||||
import com.agendaestudantil.servico.EventoServico;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/eventos")
|
||||
public class EventoControlador {
|
||||
|
||||
private final EventoServico eventoServico;
|
||||
|
||||
public EventoControlador(EventoServico eventoServico) {
|
||||
this.eventoServico = eventoServico;
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public ResponseEntity<RespostaApi<RespostaEventoDTO>> criarEvento(
|
||||
@Valid @RequestBody RequisicaoEventoDTO dto,
|
||||
@AuthenticationPrincipal UserDetails userDetails) {
|
||||
String estudanteId = userDetails.getUsername();
|
||||
Evento evento = new Evento();
|
||||
evento.setTitulo(dto.titulo());
|
||||
evento.setDescricao(dto.descricao());
|
||||
evento.setTipo(dto.tipo());
|
||||
evento.setLocal(dto.local());
|
||||
evento.setDataHora(dto.dataHora());
|
||||
evento.setDisciplinaId(dto.disciplinaId());
|
||||
|
||||
RespostaEventoDTO resposta = eventoServico.criarEvento(evento, estudanteId);
|
||||
return ResponseEntity.status(HttpStatus.CREATED).body(RespostaApi.sucesso(resposta));
|
||||
}
|
||||
|
||||
@GetMapping("/me")
|
||||
public ResponseEntity<RespostaApi<List<RespostaEventoDTO>>> listarPorEstudante(
|
||||
@AuthenticationPrincipal UserDetails userDetails) {
|
||||
String estudanteId = userDetails.getUsername();
|
||||
List<RespostaEventoDTO> eventos = eventoServico.listarPorEstudante(estudanteId);
|
||||
return ResponseEntity.ok(RespostaApi.sucesso(eventos));
|
||||
}
|
||||
|
||||
@GetMapping("/me/periodo")
|
||||
public ResponseEntity<RespostaApi<List<RespostaEventoDTO>>> listarPorPeriodo(
|
||||
@AuthenticationPrincipal UserDetails userDetails,
|
||||
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime inicio,
|
||||
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime fim) {
|
||||
String estudanteId = userDetails.getUsername();
|
||||
List<RespostaEventoDTO> eventos = eventoServico.listarPorPeriodo(estudanteId, inicio, fim);
|
||||
return ResponseEntity.ok(RespostaApi.sucesso(eventos));
|
||||
}
|
||||
|
||||
@GetMapping("/me/proximos")
|
||||
public ResponseEntity<RespostaApi<List<RespostaEventoDTO>>> listarProximosEventos(
|
||||
@AuthenticationPrincipal UserDetails userDetails) {
|
||||
String estudanteId = userDetails.getUsername();
|
||||
List<RespostaEventoDTO> eventos = eventoServico.listarProximosEventos(estudanteId);
|
||||
return ResponseEntity.ok(RespostaApi.sucesso(eventos));
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public ResponseEntity<RespostaApi<RespostaEventoDTO>> buscarPorId(@PathVariable String id) {
|
||||
RespostaEventoDTO evento = eventoServico.buscarPorId(id);
|
||||
return ResponseEntity.ok(RespostaApi.sucesso(evento));
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
public ResponseEntity<RespostaApi<RespostaEventoDTO>> atualizarEvento(
|
||||
@PathVariable String id,
|
||||
@Valid @RequestBody RequisicaoEventoDTO dto) {
|
||||
RespostaEventoDTO resposta = eventoServico.atualizarEvento(id, dto);
|
||||
return ResponseEntity.ok(RespostaApi.sucesso(resposta));
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
public ResponseEntity<RespostaApi<Void>> excluirEvento(@PathVariable String id) {
|
||||
eventoServico.excluirEvento(id);
|
||||
return ResponseEntity.status(HttpStatus.NO_CONTENT).body(RespostaApi.sucesso(null));
|
||||
}
|
||||
|
||||
@PatchMapping("/{id}/cancelar")
|
||||
public ResponseEntity<RespostaApi<RespostaEventoDTO>> cancelarEvento(@PathVariable String id) {
|
||||
RespostaEventoDTO evento = eventoServico.cancelarEvento(id);
|
||||
return ResponseEntity.ok(RespostaApi.sucesso(evento));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.agendaestudantil.controlador;
|
||||
|
||||
import com.agendaestudantil.dto.RespostaApi;
|
||||
import com.agendaestudantil.dto.RespostaNotificacaoDTO;
|
||||
import com.agendaestudantil.servico.NotificacaoServico;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/notificacoes")
|
||||
public class NotificacaoControlador {
|
||||
|
||||
private final NotificacaoServico notificacaoServico;
|
||||
|
||||
public NotificacaoControlador(NotificacaoServico notificacaoServico) {
|
||||
this.notificacaoServico = notificacaoServico;
|
||||
}
|
||||
|
||||
@GetMapping("/me")
|
||||
public ResponseEntity<RespostaApi<List<RespostaNotificacaoDTO>>> listarTodas(
|
||||
@AuthenticationPrincipal UserDetails userDetails) {
|
||||
String estudanteId = userDetails.getUsername();
|
||||
List<RespostaNotificacaoDTO> notificacoes = notificacaoServico.listarTodas(estudanteId);
|
||||
return ResponseEntity.ok(RespostaApi.sucesso(notificacoes));
|
||||
}
|
||||
|
||||
@GetMapping("/me/nao-lidas")
|
||||
public ResponseEntity<RespostaApi<List<RespostaNotificacaoDTO>>> listarNaoLidas(
|
||||
@AuthenticationPrincipal UserDetails userDetails) {
|
||||
String estudanteId = userDetails.getUsername();
|
||||
List<RespostaNotificacaoDTO> notificacoes = notificacaoServico.listarNaoLidas(estudanteId);
|
||||
return ResponseEntity.ok(RespostaApi.sucesso(notificacoes));
|
||||
}
|
||||
|
||||
@GetMapping("/me/contagem")
|
||||
public ResponseEntity<RespostaApi<Map<String, Long>>> contarNaoLidas(
|
||||
@AuthenticationPrincipal UserDetails userDetails) {
|
||||
String estudanteId = userDetails.getUsername();
|
||||
long total = notificacaoServico.contarNaoLidas(estudanteId);
|
||||
return ResponseEntity.ok(RespostaApi.sucesso(Map.of("total", total)));
|
||||
}
|
||||
|
||||
@PatchMapping("/{id}/ler")
|
||||
public ResponseEntity<RespostaApi<RespostaNotificacaoDTO>> marcarComoLida(@PathVariable String id) {
|
||||
RespostaNotificacaoDTO notificacao = notificacaoServico.marcarComoLida(id);
|
||||
return ResponseEntity.ok(RespostaApi.sucesso(notificacao));
|
||||
}
|
||||
|
||||
@PatchMapping("/me/ler-todas")
|
||||
public ResponseEntity<RespostaApi<Void>> marcarTodasComoLidas(
|
||||
@AuthenticationPrincipal UserDetails userDetails) {
|
||||
String estudanteId = userDetails.getUsername();
|
||||
notificacaoServico.marcarTodasComoLidas(estudanteId);
|
||||
return ResponseEntity.ok(RespostaApi.sucesso(null));
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
public ResponseEntity<RespostaApi<Void>> excluirNotificacao(@PathVariable String id) {
|
||||
notificacaoServico.excluirNotificacao(id);
|
||||
return ResponseEntity.status(HttpStatus.NO_CONTENT).body(RespostaApi.sucesso(null));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package com.agendaestudantil.controlador;
|
||||
|
||||
import com.agendaestudantil.dto.RespostaApi;
|
||||
import com.agendaestudantil.dto.RequisicaoTarefaDTO;
|
||||
import com.agendaestudantil.dto.RespostaTarefaDTO;
|
||||
import com.agendaestudantil.servico.TarefaServico;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/tarefas")
|
||||
public class TarefaControlador {
|
||||
|
||||
private final TarefaServico tarefaServico;
|
||||
|
||||
public TarefaControlador(TarefaServico tarefaServico) {
|
||||
this.tarefaServico = tarefaServico;
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public ResponseEntity<RespostaApi<RespostaTarefaDTO>> criarTarefa(@Valid @RequestBody RequisicaoTarefaDTO dto) {
|
||||
RespostaTarefaDTO tarefa = tarefaServico.criarTarefa(dto);
|
||||
return ResponseEntity.status(HttpStatus.CREATED).body(RespostaApi.sucesso(tarefa));
|
||||
}
|
||||
|
||||
@GetMapping("/me")
|
||||
public ResponseEntity<RespostaApi<List<RespostaTarefaDTO>>> listarTarefasPorEstudante(
|
||||
@AuthenticationPrincipal UserDetails userDetails) {
|
||||
String estudanteId = userDetails.getUsername();
|
||||
List<RespostaTarefaDTO> tarefas = tarefaServico.listarTarefasPorEstudante(estudanteId);
|
||||
return ResponseEntity.ok(RespostaApi.sucesso(tarefas));
|
||||
}
|
||||
|
||||
@GetMapping("/me/pendentes")
|
||||
public ResponseEntity<RespostaApi<List<RespostaTarefaDTO>>> listarTarefasPendentes(
|
||||
@AuthenticationPrincipal UserDetails userDetails) {
|
||||
String estudanteId = userDetails.getUsername();
|
||||
List<RespostaTarefaDTO> tarefas = tarefaServico.listarTarefasPendentes(estudanteId);
|
||||
return ResponseEntity.ok(RespostaApi.sucesso(tarefas));
|
||||
}
|
||||
|
||||
@GetMapping("/me/data")
|
||||
public ResponseEntity<RespostaApi<List<RespostaTarefaDTO>>> listarTarefasPorData(
|
||||
@AuthenticationPrincipal UserDetails userDetails,
|
||||
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate data) {
|
||||
String estudanteId = userDetails.getUsername();
|
||||
List<RespostaTarefaDTO> tarefas = tarefaServico.listarTarefasPorData(estudanteId, data);
|
||||
return ResponseEntity.ok(RespostaApi.sucesso(tarefas));
|
||||
}
|
||||
|
||||
@GetMapping("/me/periodo")
|
||||
public ResponseEntity<RespostaApi<List<RespostaTarefaDTO>>> listarTarefasPorPeriodo(
|
||||
@AuthenticationPrincipal UserDetails userDetails,
|
||||
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate inicio,
|
||||
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate fim) {
|
||||
String estudanteId = userDetails.getUsername();
|
||||
List<RespostaTarefaDTO> tarefas = tarefaServico.listarTarefasPorPeriodo(estudanteId, inicio, fim);
|
||||
return ResponseEntity.ok(RespostaApi.sucesso(tarefas));
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public ResponseEntity<RespostaApi<RespostaTarefaDTO>> buscarTarefaPorId(@PathVariable String id) {
|
||||
RespostaTarefaDTO dto = tarefaServico.buscarTarefaPorId(id);
|
||||
return ResponseEntity.ok(RespostaApi.sucesso(dto));
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
public ResponseEntity<RespostaApi<RespostaTarefaDTO>> atualizarTarefa(@PathVariable String id,
|
||||
@Valid @RequestBody RequisicaoTarefaDTO dto) {
|
||||
RespostaTarefaDTO tarefa = tarefaServico.atualizarTarefa(id, dto);
|
||||
return ResponseEntity.ok(RespostaApi.sucesso(tarefa));
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
public ResponseEntity<RespostaApi<Void>> excluirTarefa(@PathVariable String id) {
|
||||
tarefaServico.excluirTarefa(id);
|
||||
return ResponseEntity.status(HttpStatus.NO_CONTENT).body(RespostaApi.sucesso(null));
|
||||
}
|
||||
|
||||
@PatchMapping("/{id}/concluir")
|
||||
public ResponseEntity<RespostaApi<RespostaTarefaDTO>> marcarConcluida(@PathVariable String id) {
|
||||
RespostaTarefaDTO tarefa = tarefaServico.marcarConcluida(id);
|
||||
return ResponseEntity.ok(RespostaApi.sucesso(tarefa));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.agendaestudantil.dto;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Min;
|
||||
|
||||
public record RequisicaoAtualizacaoEstudanteDTO(
|
||||
@NotBlank String nome,
|
||||
@NotBlank String curso,
|
||||
@NotNull @Min(1) Integer periodo
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.agendaestudantil.dto;
|
||||
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
public record RequisicaoCadastroDTO(
|
||||
@NotBlank String nome,
|
||||
@Email @NotBlank String email,
|
||||
@NotBlank @Size(min = 6) String senha,
|
||||
@NotBlank String curso,
|
||||
@NotNull @Min(1) Integer periodo
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.agendaestudantil.dto;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
|
||||
public record RequisicaoDisciplinaDTO(
|
||||
@NotBlank String nome,
|
||||
String professor,
|
||||
String sala,
|
||||
String cor
|
||||
) {}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.agendaestudantil.dto;
|
||||
|
||||
import com.agendaestudantil.entidade.Evento;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public record RequisicaoEventoDTO(
|
||||
@NotBlank String titulo,
|
||||
String descricao,
|
||||
@NotNull Evento.TipoEvento tipo,
|
||||
String local,
|
||||
String disciplinaId,
|
||||
@NotNull LocalDateTime dataHora
|
||||
) {}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.agendaestudantil.dto;
|
||||
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
|
||||
public record RequisicaoLoginDTO(
|
||||
@Email @NotBlank String email,
|
||||
@NotBlank String senha
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.agendaestudantil.dto;
|
||||
|
||||
import com.agendaestudantil.entidade.Tarefa;
|
||||
import jakarta.validation.constraints.FutureOrPresent;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
public record RequisicaoTarefaDTO(
|
||||
@NotBlank String titulo,
|
||||
String descricao,
|
||||
@NotNull(message = "Prioridade é obrigatória") Tarefa.Prioridade prioridade,
|
||||
Tarefa.StatusTarefa status,
|
||||
@NotNull @FutureOrPresent LocalDate dataEntrega,
|
||||
String disciplinaId
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.agendaestudantil.dto;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
public record RequisicaoTrocaSenhaDTO(
|
||||
@NotBlank String senhaAtual,
|
||||
@NotBlank @Size(min = 6) String novaSenha
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.agendaestudantil.dto;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public record RespostaApi<T>(T data, String message, LocalDateTime timestamp) {
|
||||
public static <T> RespostaApi<T> sucesso(T data) {
|
||||
return new RespostaApi<>(data, "Sucesso", LocalDateTime.now());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.agendaestudantil.dto;
|
||||
|
||||
public record RespostaDisciplinaDTO(
|
||||
String id,
|
||||
String estudanteId,
|
||||
String nome,
|
||||
String professor,
|
||||
String sala,
|
||||
String cor
|
||||
) {}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.agendaestudantil.dto;
|
||||
|
||||
public record RespostaEstudanteDTO(
|
||||
String id,
|
||||
String nome,
|
||||
String email,
|
||||
String curso,
|
||||
Integer periodo
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.agendaestudantil.dto;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public record RespostaEventoDTO(
|
||||
String id,
|
||||
String estudanteId,
|
||||
String titulo,
|
||||
String descricao,
|
||||
String tipo,
|
||||
String local,
|
||||
String disciplinaId,
|
||||
LocalDateTime dataHora,
|
||||
String status,
|
||||
String nomeDisciplina
|
||||
) {}
|
||||
@@ -0,0 +1,4 @@
|
||||
package com.agendaestudantil.dto;
|
||||
|
||||
public record RespostaLoginDTO(String token, RespostaEstudanteDTO estudante) {
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.agendaestudantil.dto;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public record RespostaNotificacaoDTO(
|
||||
String id,
|
||||
String titulo,
|
||||
String mensagem,
|
||||
String tipo,
|
||||
String referenciaId,
|
||||
String tipoReferencia,
|
||||
boolean lida,
|
||||
LocalDateTime dataGeracao
|
||||
) {}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.agendaestudantil.dto;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
public record RespostaTarefaDTO(
|
||||
String id,
|
||||
String titulo,
|
||||
String descricao,
|
||||
String prioridade,
|
||||
String status,
|
||||
LocalDate dataEntrega,
|
||||
String disciplinaId,
|
||||
String estudanteId
|
||||
) {}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.agendaestudantil.entidade;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.mongodb.core.index.CompoundIndex;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Document(collection = "disciplinas")
|
||||
@CompoundIndex(name = "estudante_nome_idx", def = "{estudanteId: 1, nome: 1}")
|
||||
public class Disciplina extends EntidadeAuditoria {
|
||||
|
||||
@Id
|
||||
private String id;
|
||||
private String estudanteId;
|
||||
private String nome;
|
||||
private String professor;
|
||||
private String sala;
|
||||
private String cor;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.agendaestudantil.entidade;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.data.annotation.CreatedDate;
|
||||
import org.springframework.data.annotation.LastModifiedDate;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public abstract class EntidadeAuditoria {
|
||||
|
||||
@CreatedDate
|
||||
private LocalDateTime dataCriacao;
|
||||
|
||||
@LastModifiedDate
|
||||
private LocalDateTime dataAtualizacao;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.agendaestudantil.entidade;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.mongodb.core.index.Indexed;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Document(collection = "estudantes")
|
||||
public class Estudante extends EntidadeAuditoria {
|
||||
|
||||
@Id
|
||||
private String id;
|
||||
|
||||
@Indexed(unique = true)
|
||||
private String email;
|
||||
|
||||
private String nome;
|
||||
|
||||
private String senha;
|
||||
|
||||
private String curso;
|
||||
|
||||
private Integer periodo;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.agendaestudantil.entidade;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.mongodb.core.index.CompoundIndex;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Document(collection = "eventos")
|
||||
@CompoundIndex(name = "estudante_data_hora_idx", def = "{estudanteId: 1, dataHora: 1}")
|
||||
public class Evento extends EntidadeAuditoria {
|
||||
|
||||
@Id
|
||||
private String id;
|
||||
private String estudanteId;
|
||||
private String titulo;
|
||||
private String descricao;
|
||||
private TipoEvento tipo;
|
||||
private String local;
|
||||
private String disciplinaId;
|
||||
private LocalDateTime dataHora;
|
||||
private StatusEvento status;
|
||||
|
||||
public enum TipoEvento {
|
||||
AULA, PROVA, TRABALHO, ESTUDO, EXAME, OUTRO
|
||||
}
|
||||
|
||||
public enum StatusEvento {
|
||||
ATIVO, CANCELADO
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.agendaestudantil.entidade;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.mongodb.core.index.CompoundIndex;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Document(collection = "notificacoes")
|
||||
@CompoundIndex(name = "estudante_lida_idx", def = "{estudanteId: 1, lida: 1}")
|
||||
public class Notificacao extends EntidadeAuditoria {
|
||||
|
||||
@Id
|
||||
private String id;
|
||||
private String estudanteId;
|
||||
private String titulo;
|
||||
private String mensagem;
|
||||
private TipoNotificacao tipo;
|
||||
private String referenciaId;
|
||||
private TipoReferencia tipoReferencia;
|
||||
private boolean lida;
|
||||
private LocalDateTime dataGeracao;
|
||||
|
||||
public enum TipoNotificacao {
|
||||
PRAZO_PROXIMO, TAREFA_ATRASADA, EVENTO_PROXIMO
|
||||
}
|
||||
|
||||
public enum TipoReferencia {
|
||||
TAREFA, EVENTO
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.agendaestudantil.entidade;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.mongodb.core.index.CompoundIndex;
|
||||
import org.springframework.data.mongodb.core.index.CompoundIndexes;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Document(collection = "tarefas")
|
||||
@CompoundIndexes({
|
||||
@CompoundIndex(name = "estudante_data_entrega_idx", def = "{estudanteId: 1, dataEntrega: 1}"),
|
||||
@CompoundIndex(name = "estudante_status_idx", def = "{estudanteId: 1, status: 1}")
|
||||
})
|
||||
public class Tarefa extends EntidadeAuditoria {
|
||||
|
||||
@Id
|
||||
private String id;
|
||||
private String titulo;
|
||||
private String descricao;
|
||||
private Prioridade prioridade;
|
||||
private StatusTarefa status;
|
||||
private LocalDate dataEntrega;
|
||||
private String disciplinaId;
|
||||
private String estudanteId;
|
||||
|
||||
public enum Prioridade {
|
||||
BAIXA, MEDIA, ALTA, URGENTE
|
||||
}
|
||||
|
||||
public enum StatusTarefa {
|
||||
PENDENTE, EM_ANDAMENTO, CONCLUIDA, ATRASADA
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.agendaestudantil.excecao;
|
||||
|
||||
public class ExcecaoNegocio extends RuntimeException {
|
||||
public ExcecaoNegocio(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.agendaestudantil.excecao;
|
||||
|
||||
public class ExcecaoRecursoNaoEncontrado extends RuntimeException {
|
||||
public ExcecaoRecursoNaoEncontrado(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.agendaestudantil.excecao;
|
||||
|
||||
import com.agendaestudantil.dto.RespostaApi;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.validation.FieldError;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@RestControllerAdvice
|
||||
public class ManipuladorExcecaoGlobal {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(ManipuladorExcecaoGlobal.class);
|
||||
|
||||
@ExceptionHandler(ExcecaoRecursoNaoEncontrado.class)
|
||||
public ResponseEntity<RespostaApi<Void>> handleResourceNotFound(ExcecaoRecursoNaoEncontrado ex) {
|
||||
return ResponseEntity.status(HttpStatus.NOT_FOUND)
|
||||
.body(new RespostaApi<>(null, ex.getMessage(), LocalDateTime.now()));
|
||||
}
|
||||
|
||||
@ExceptionHandler(ExcecaoNegocio.class)
|
||||
public ResponseEntity<RespostaApi<Void>> handleExcecaoNegocio(ExcecaoNegocio ex) {
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
|
||||
.body(new RespostaApi<>(null, ex.getMessage(), LocalDateTime.now()));
|
||||
}
|
||||
|
||||
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||
public ResponseEntity<RespostaApi<Map<String, String>>> handleValidationException(
|
||||
MethodArgumentNotValidException ex) {
|
||||
Map<String, String> errors = new HashMap<>();
|
||||
for (FieldError error : ex.getBindingResult().getFieldErrors()) {
|
||||
errors.put(error.getField(), error.getDefaultMessage());
|
||||
}
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
|
||||
.body(new RespostaApi<>(errors, "Falha na validação", LocalDateTime.now()));
|
||||
}
|
||||
|
||||
@ExceptionHandler(ResponseStatusException.class)
|
||||
public ResponseEntity<RespostaApi<Void>> handleResponseStatusException(ResponseStatusException ex) {
|
||||
return ResponseEntity.status(ex.getStatusCode())
|
||||
.body(new RespostaApi<>(null, ex.getReason(), LocalDateTime.now()));
|
||||
}
|
||||
|
||||
@ExceptionHandler(Exception.class)
|
||||
public ResponseEntity<RespostaApi<Void>> handleGenericException(Exception ex) {
|
||||
log.error("Erro interno no servidor", ex);
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
.body(new RespostaApi<>(null, "Erro interno no servidor", LocalDateTime.now()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.agendaestudantil.filtro;
|
||||
|
||||
import com.agendaestudantil.utilitario.UtilJwt;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@Component
|
||||
public class FiltroJwt extends OncePerRequestFilter {
|
||||
|
||||
private final UtilJwt utilJwt;
|
||||
private final UserDetailsService userDetailsService;
|
||||
|
||||
public FiltroJwt(UtilJwt utilJwt, UserDetailsService userDetailsService) {
|
||||
this.utilJwt = utilJwt;
|
||||
this.userDetailsService = userDetailsService;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldNotFilter(HttpServletRequest request) {
|
||||
String path = request.getRequestURI();
|
||||
return path.equals("/") || path.equals("/index.html") || path.equals("/favicon.ico")
|
||||
|| path.startsWith("/static/") || path.startsWith("/css/") || path.startsWith("/js/")
|
||||
|| path.startsWith("/img/") || path.endsWith(".css") || path.endsWith(".js")
|
||||
|| path.endsWith(".ico") || path.endsWith(".html");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
|
||||
String header = request.getHeader("Authorization");
|
||||
String token = null;
|
||||
String estudanteId = null;
|
||||
|
||||
if (header != null && header.startsWith("Bearer ")) {
|
||||
token = header.substring(7);
|
||||
}
|
||||
|
||||
if (token != null && utilJwt.validateToken(token)) {
|
||||
estudanteId = utilJwt.getEstudanteIdFromToken(token);
|
||||
|
||||
if (SecurityContextHolder.getContext().getAuthentication() == null) {
|
||||
UserDetails userDetails = userDetailsService.loadUserByUsername(estudanteId);
|
||||
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
|
||||
userDetails, null, userDetails.getAuthorities());
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
}
|
||||
}
|
||||
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.agendaestudantil.repositorio;
|
||||
|
||||
import com.agendaestudantil.entidade.Disciplina;
|
||||
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface DisciplinaRepositorio extends MongoRepository<Disciplina, String> {
|
||||
List<Disciplina> findByEstudanteId(String estudanteId);
|
||||
|
||||
void deleteByEstudanteId(String estudanteId);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.agendaestudantil.repositorio;
|
||||
|
||||
import com.agendaestudantil.entidade.Estudante;
|
||||
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
public interface EstudanteRepositorio extends MongoRepository<Estudante, String> {
|
||||
Optional<Estudante> findByEmail(String email);
|
||||
boolean existsByEmail(String email);
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.agendaestudantil.repositorio;
|
||||
|
||||
import com.agendaestudantil.entidade.Evento;
|
||||
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||
import org.springframework.data.mongodb.repository.Query;
|
||||
|
||||
import org.springframework.stereotype.Repository;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface EventoRepositorio extends MongoRepository<Evento, String> {
|
||||
List<Evento> findByEstudanteId(String estudanteId);
|
||||
|
||||
List<Evento> findByDisciplinaId(String disciplinaId);
|
||||
|
||||
@Query("{'estudanteId': ?0, 'dataHora': {$gte: ?1, $lte: ?2}}")
|
||||
List<Evento> findByEstudanteIdAndDataHoraBetween(String estudanteId, LocalDateTime inicio, LocalDateTime fim);
|
||||
|
||||
@Query("{'estudanteId': ?0, 'dataHora': {$gte: ?1}}")
|
||||
List<Evento> findProximosEventosByEstudanteId(String estudanteId, LocalDateTime data);
|
||||
|
||||
void deleteByEstudanteId(String estudanteId);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.agendaestudantil.repositorio;
|
||||
|
||||
import com.agendaestudantil.entidade.Notificacao;
|
||||
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface NotificacaoRepositorio extends MongoRepository<Notificacao, String> {
|
||||
|
||||
List<Notificacao> findByEstudanteIdAndLidaFalse(String estudanteId);
|
||||
|
||||
List<Notificacao> findByEstudanteId(String estudanteId);
|
||||
|
||||
long countByEstudanteIdAndLidaFalse(String estudanteId);
|
||||
|
||||
void deleteByEstudanteId(String estudanteId);
|
||||
|
||||
boolean existsByEstudanteIdAndReferenciaId(String estudanteId, String referenciaId);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.agendaestudantil.repositorio;
|
||||
|
||||
import com.agendaestudantil.entidade.Tarefa;
|
||||
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||
import org.springframework.data.mongodb.repository.Query;
|
||||
|
||||
import org.springframework.stereotype.Repository;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface TarefaRepositorio extends MongoRepository<Tarefa, String> {
|
||||
List<Tarefa> findByEstudanteId(String estudanteId);
|
||||
|
||||
List<Tarefa> findByEstudanteIdAndStatus(String estudanteId, Tarefa.StatusTarefa status);
|
||||
|
||||
List<Tarefa> findByDisciplinaId(String disciplinaId);
|
||||
|
||||
@Query("{'estudanteId': ?0, 'dataEntrega': ?1}")
|
||||
List<Tarefa> findByEstudanteIdAndDataEntrega(String estudanteId, LocalDate data);
|
||||
|
||||
@Query("{'estudanteId': ?0, 'dataEntrega': {$gte: ?1, $lte: ?2}}")
|
||||
List<Tarefa> findByEstudanteIdAndDataEntregaBetween(String estudanteId, LocalDate inicio, LocalDate fim);
|
||||
|
||||
@Query("{'estudanteId': ?0, 'status': {$ne: ?1}}")
|
||||
List<Tarefa> findTarefasPendentesByEstudanteId(String estudanteId, Tarefa.StatusTarefa status);
|
||||
|
||||
void deleteByEstudanteId(String estudanteId);
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.agendaestudantil.seguranca;
|
||||
|
||||
import com.agendaestudantil.entidade.Estudante;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
public class DetalhesUsuarioPersonalizado implements UserDetails {
|
||||
|
||||
private final Estudante estudante;
|
||||
|
||||
public DetalhesUsuarioPersonalizado(Estudante estudante) {
|
||||
this.estudante = estudante;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||
return Collections.singleton(new SimpleGrantedAuthority("ROLE_USER"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPassword() {
|
||||
return estudante.getSenha();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return estudante.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccountNonExpired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccountNonLocked() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCredentialsNonExpired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.agendaestudantil.seguranca;
|
||||
|
||||
import com.agendaestudantil.entidade.Estudante;
|
||||
import com.agendaestudantil.repositorio.EstudanteRepositorio;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class ServicoAutenticacaoUsuario implements UserDetailsService {
|
||||
|
||||
private final EstudanteRepositorio estudanteRepositorio;
|
||||
|
||||
public ServicoAutenticacaoUsuario(EstudanteRepositorio estudanteRepositorio) {
|
||||
this.estudanteRepositorio = estudanteRepositorio;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String estudanteId) throws UsernameNotFoundException {
|
||||
Estudante estudante = estudanteRepositorio.findById(estudanteId)
|
||||
.orElseThrow(() -> new UsernameNotFoundException("Estudante não encontrado"));
|
||||
|
||||
return new DetalhesUsuarioPersonalizado(estudante);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
package com.agendaestudantil.servico;
|
||||
|
||||
import com.agendaestudantil.dto.RespostaDisciplinaDTO;
|
||||
import com.agendaestudantil.entidade.Disciplina;
|
||||
import com.agendaestudantil.excecao.ExcecaoRecursoNaoEncontrado;
|
||||
import com.agendaestudantil.repositorio.DisciplinaRepositorio;
|
||||
import com.agendaestudantil.repositorio.TarefaRepositorio;
|
||||
import com.agendaestudantil.repositorio.EventoRepositorio;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class DisciplinaServico {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(DisciplinaServico.class);
|
||||
|
||||
private final DisciplinaRepositorio disciplinaRepositorio;
|
||||
private final TarefaRepositorio tarefaRepositorio;
|
||||
private final EventoRepositorio eventoRepositorio;
|
||||
|
||||
public DisciplinaServico(DisciplinaRepositorio disciplinaRepositorio, TarefaRepositorio tarefaRepositorio,
|
||||
EventoRepositorio eventoRepositorio) {
|
||||
this.disciplinaRepositorio = disciplinaRepositorio;
|
||||
this.tarefaRepositorio = tarefaRepositorio;
|
||||
this.eventoRepositorio = eventoRepositorio;
|
||||
}
|
||||
|
||||
private void validarAcesso(String estudanteId) {
|
||||
String authUser = SecurityContextHolder.getContext().getAuthentication().getName();
|
||||
if (!authUser.equals(estudanteId)) {
|
||||
log.error("Acesso negado. Usuário {} tentou acessar recurso do estudante {}", authUser, estudanteId);
|
||||
throw new ResponseStatusException(HttpStatus.FORBIDDEN, "Acesso negado");
|
||||
}
|
||||
}
|
||||
|
||||
public RespostaDisciplinaDTO criarDisciplina(Disciplina disciplina, String estudanteId) {
|
||||
log.debug("Criando disciplina para estudante: {}", estudanteId);
|
||||
validarAcesso(estudanteId);
|
||||
|
||||
disciplina.setEstudanteId(estudanteId);
|
||||
Disciplina salva = disciplinaRepositorio.save(disciplina);
|
||||
return toDTO(salva);
|
||||
}
|
||||
|
||||
public List<RespostaDisciplinaDTO> listarPorEstudante(String estudanteId) {
|
||||
log.debug("Listando disciplinas para estudante: {}", estudanteId);
|
||||
validarAcesso(estudanteId);
|
||||
|
||||
return disciplinaRepositorio.findByEstudanteId(estudanteId).stream()
|
||||
.map(this::toDTO)
|
||||
.toList();
|
||||
}
|
||||
|
||||
public RespostaDisciplinaDTO buscarPorId(String id, String estudanteId) {
|
||||
Disciplina disciplina = getDisciplinaEntity(id);
|
||||
validarAcesso(disciplina.getEstudanteId());
|
||||
return toDTO(disciplina);
|
||||
}
|
||||
|
||||
public RespostaDisciplinaDTO atualizarDisciplina(String id, Disciplina disciplinaAtualizada, String estudanteId) {
|
||||
Disciplina disciplina = getDisciplinaEntity(id);
|
||||
validarAcesso(disciplina.getEstudanteId());
|
||||
|
||||
disciplina.setNome(disciplinaAtualizada.getNome());
|
||||
disciplina.setProfessor(disciplinaAtualizada.getProfessor());
|
||||
disciplina.setSala(disciplinaAtualizada.getSala());
|
||||
disciplina.setCor(disciplinaAtualizada.getCor());
|
||||
|
||||
return toDTO(disciplinaRepositorio.save(disciplina));
|
||||
}
|
||||
|
||||
public void excluirDisciplina(String id, String estudanteId) {
|
||||
Disciplina disciplina = getDisciplinaEntity(id);
|
||||
validarAcesso(disciplina.getEstudanteId());
|
||||
tarefaRepositorio.findByDisciplinaId(id).forEach(tarefa -> {
|
||||
tarefa.setDisciplinaId(null);
|
||||
tarefaRepositorio.save(tarefa);
|
||||
});
|
||||
eventoRepositorio.findByDisciplinaId(id).forEach(evento -> {
|
||||
evento.setDisciplinaId(null);
|
||||
eventoRepositorio.save(evento);
|
||||
});
|
||||
disciplinaRepositorio.delete(disciplina);
|
||||
}
|
||||
|
||||
private Disciplina getDisciplinaEntity(String id) {
|
||||
return disciplinaRepositorio.findById(id)
|
||||
.orElseThrow(() -> new ExcecaoRecursoNaoEncontrado("Disciplina não encontrada"));
|
||||
}
|
||||
|
||||
private RespostaDisciplinaDTO toDTO(Disciplina disciplina) {
|
||||
return new RespostaDisciplinaDTO(
|
||||
disciplina.getId(),
|
||||
disciplina.getEstudanteId(),
|
||||
disciplina.getNome(),
|
||||
disciplina.getProfessor(),
|
||||
disciplina.getSala(),
|
||||
disciplina.getCor()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
package com.agendaestudantil.servico;
|
||||
|
||||
import com.agendaestudantil.dto.RequisicaoAtualizacaoEstudanteDTO;
|
||||
import com.agendaestudantil.dto.RequisicaoCadastroDTO;
|
||||
import com.agendaestudantil.dto.RespostaEstudanteDTO;
|
||||
import com.agendaestudantil.dto.RequisicaoLoginDTO;
|
||||
import com.agendaestudantil.dto.RespostaLoginDTO;
|
||||
import com.agendaestudantil.dto.RequisicaoTrocaSenhaDTO;
|
||||
import com.agendaestudantil.entidade.Estudante;
|
||||
import com.agendaestudantil.excecao.ExcecaoNegocio;
|
||||
import com.agendaestudantil.excecao.ExcecaoRecursoNaoEncontrado;
|
||||
import com.agendaestudantil.repositorio.EstudanteRepositorio;
|
||||
import com.agendaestudantil.repositorio.EventoRepositorio;
|
||||
import com.agendaestudantil.repositorio.TarefaRepositorio;
|
||||
import com.agendaestudantil.repositorio.DisciplinaRepositorio;
|
||||
import com.agendaestudantil.utilitario.UtilJwt;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Service
|
||||
public class EstudanteServico {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(EstudanteServico.class);
|
||||
|
||||
private final EstudanteRepositorio estudanteRepositorio;
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
private final UtilJwt utilJwt;
|
||||
private final TarefaRepositorio tarefaRepositorio;
|
||||
private final EventoRepositorio eventoRepositorio;
|
||||
private final DisciplinaRepositorio disciplinaRepositorio;
|
||||
|
||||
public EstudanteServico(EstudanteRepositorio estudanteRepositorio, PasswordEncoder passwordEncoder,
|
||||
UtilJwt utilJwt, TarefaRepositorio tarefaRepositorio, EventoRepositorio eventoRepositorio,
|
||||
DisciplinaRepositorio disciplinaRepositorio) {
|
||||
this.estudanteRepositorio = estudanteRepositorio;
|
||||
this.passwordEncoder = passwordEncoder;
|
||||
this.utilJwt = utilJwt;
|
||||
this.tarefaRepositorio = tarefaRepositorio;
|
||||
this.eventoRepositorio = eventoRepositorio;
|
||||
this.disciplinaRepositorio = disciplinaRepositorio;
|
||||
}
|
||||
|
||||
public RespostaEstudanteDTO cadastrar(RequisicaoCadastroDTO dto) {
|
||||
log.debug("Acessando método cadastrar para email: {}", dto.email());
|
||||
Optional<Estudante> existente = estudanteRepositorio.findByEmail(dto.email());
|
||||
if (existente.isPresent()) {
|
||||
log.error("Email já cadastrado: {}", dto.email());
|
||||
throw new ExcecaoNegocio("Email já cadastrado");
|
||||
}
|
||||
|
||||
Estudante estudante = new Estudante();
|
||||
estudante.setNome(dto.nome());
|
||||
estudante.setEmail(dto.email());
|
||||
estudante.setSenha(passwordEncoder.encode(dto.senha()));
|
||||
estudante.setCurso(dto.curso());
|
||||
estudante.setPeriodo(dto.periodo());
|
||||
|
||||
Estudante salvo = estudanteRepositorio.save(estudante);
|
||||
return toResponse(salvo);
|
||||
}
|
||||
|
||||
public RespostaLoginDTO login(RequisicaoLoginDTO dto) {
|
||||
log.debug("Acessando método login para email: {}", dto.email());
|
||||
Optional<Estudante> estudanteParam = estudanteRepositorio.findByEmail(dto.email());
|
||||
|
||||
if (estudanteParam.isEmpty()) {
|
||||
log.error("Email ou senha incorretos para email: {}", dto.email());
|
||||
throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "Email ou senha incorretos");
|
||||
}
|
||||
|
||||
Estudante estudante = estudanteParam.get();
|
||||
|
||||
if (!passwordEncoder.matches(dto.senha(), estudante.getSenha())) {
|
||||
log.error("Falha ao validar senha para email: {}", dto.email());
|
||||
throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "Email ou senha incorretos");
|
||||
}
|
||||
|
||||
String token = utilJwt.generateToken(estudante.getId());
|
||||
return new RespostaLoginDTO(token, toResponse(estudante));
|
||||
}
|
||||
|
||||
public RespostaEstudanteDTO buscarPorId(String id) {
|
||||
Estudante estudante = estudanteRepositorio.findById(id)
|
||||
.orElseThrow(() -> new ExcecaoRecursoNaoEncontrado("Estudante não encontrado"));
|
||||
return toResponse(estudante);
|
||||
}
|
||||
|
||||
public RespostaEstudanteDTO atualizar(String id, RequisicaoAtualizacaoEstudanteDTO dto) {
|
||||
Estudante estudante = estudanteRepositorio.findById(id)
|
||||
.orElseThrow(() -> new ExcecaoRecursoNaoEncontrado("Estudante não encontrado"));
|
||||
|
||||
estudante.setNome(dto.nome());
|
||||
estudante.setCurso(dto.curso());
|
||||
estudante.setPeriodo(dto.periodo());
|
||||
|
||||
Estudante atualizado = estudanteRepositorio.save(estudante);
|
||||
return toResponse(atualizado);
|
||||
}
|
||||
|
||||
public void trocarSenha(String id, RequisicaoTrocaSenhaDTO dto) {
|
||||
Estudante estudante = estudanteRepositorio.findById(id)
|
||||
.orElseThrow(() -> new ExcecaoRecursoNaoEncontrado("Estudante não encontrado"));
|
||||
|
||||
if (!passwordEncoder.matches(dto.senhaAtual(), estudante.getSenha())) {
|
||||
throw new ExcecaoNegocio("Senha atual incorreta");
|
||||
}
|
||||
|
||||
estudante.setSenha(passwordEncoder.encode(dto.novaSenha()));
|
||||
estudanteRepositorio.save(estudante);
|
||||
}
|
||||
|
||||
public void excluirConta(String id) {
|
||||
if (!estudanteRepositorio.existsById(id)) {
|
||||
throw new ExcecaoRecursoNaoEncontrado("Estudante não encontrado");
|
||||
}
|
||||
tarefaRepositorio.deleteByEstudanteId(id);
|
||||
eventoRepositorio.deleteByEstudanteId(id);
|
||||
disciplinaRepositorio.deleteByEstudanteId(id);
|
||||
estudanteRepositorio.deleteById(id);
|
||||
}
|
||||
|
||||
private RespostaEstudanteDTO toResponse(Estudante estudante) {
|
||||
return new RespostaEstudanteDTO(
|
||||
estudante.getId(),
|
||||
estudante.getNome(),
|
||||
estudante.getEmail(),
|
||||
estudante.getCurso(),
|
||||
estudante.getPeriodo());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
package com.agendaestudantil.servico;
|
||||
|
||||
import com.agendaestudantil.dto.RequisicaoEventoDTO;
|
||||
import com.agendaestudantil.dto.RespostaEventoDTO;
|
||||
import com.agendaestudantil.entidade.Disciplina;
|
||||
import com.agendaestudantil.entidade.Evento;
|
||||
import com.agendaestudantil.excecao.ExcecaoNegocio;
|
||||
import com.agendaestudantil.excecao.ExcecaoRecursoNaoEncontrado;
|
||||
import com.agendaestudantil.repositorio.DisciplinaRepositorio;
|
||||
import com.agendaestudantil.repositorio.EventoRepositorio;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class EventoServico {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(EventoServico.class);
|
||||
|
||||
private final EventoRepositorio eventoRepositorio;
|
||||
private final DisciplinaRepositorio disciplinaRepositorio;
|
||||
|
||||
public EventoServico(EventoRepositorio eventoRepositorio, DisciplinaRepositorio disciplinaRepositorio) {
|
||||
this.eventoRepositorio = eventoRepositorio;
|
||||
this.disciplinaRepositorio = disciplinaRepositorio;
|
||||
}
|
||||
|
||||
private void validarAcesso(String estudanteId) {
|
||||
String authUser = SecurityContextHolder.getContext().getAuthentication().getName();
|
||||
if (!authUser.equals(estudanteId)) {
|
||||
log.error("Acesso negado. Usuário {} tentou acessar recurso do estudante {}", authUser, estudanteId);
|
||||
throw new ResponseStatusException(HttpStatus.FORBIDDEN, "Acesso negado");
|
||||
}
|
||||
}
|
||||
|
||||
private void validarDisciplina(String disciplinaId, String estudanteId) {
|
||||
if (disciplinaId == null || disciplinaId.isBlank()) {
|
||||
return;
|
||||
}
|
||||
Disciplina disciplina = disciplinaRepositorio.findById(disciplinaId)
|
||||
.orElseThrow(() -> new ExcecaoRecursoNaoEncontrado("Disciplina não encontrada"));
|
||||
if (!disciplina.getEstudanteId().equals(estudanteId)) {
|
||||
throw new ExcecaoNegocio("Disciplina não pertence ao estudante");
|
||||
}
|
||||
}
|
||||
|
||||
public RespostaEventoDTO criarEvento(Evento evento, String estudanteId) {
|
||||
log.debug("Criando evento para estudante: {}", estudanteId);
|
||||
validarAcesso(estudanteId);
|
||||
|
||||
if (evento.getDisciplinaId() != null) {
|
||||
validarDisciplina(evento.getDisciplinaId(), estudanteId);
|
||||
}
|
||||
|
||||
evento.setEstudanteId(estudanteId);
|
||||
Evento salvo = eventoRepositorio.save(evento);
|
||||
return toDTO(salvo);
|
||||
}
|
||||
|
||||
public List<RespostaEventoDTO> listarPorEstudante(String estudanteId) {
|
||||
log.debug("Listando eventos para estudante: {}", estudanteId);
|
||||
validarAcesso(estudanteId);
|
||||
|
||||
return eventoRepositorio.findByEstudanteId(estudanteId).stream()
|
||||
.map(this::toDTO)
|
||||
.toList();
|
||||
}
|
||||
|
||||
public List<RespostaEventoDTO> listarPorPeriodo(String estudanteId, LocalDateTime inicio, LocalDateTime fim) {
|
||||
validarAcesso(estudanteId);
|
||||
return eventoRepositorio.findByEstudanteIdAndDataHoraBetween(estudanteId, inicio, fim).stream()
|
||||
.map(this::toDTO)
|
||||
.toList();
|
||||
}
|
||||
|
||||
public List<RespostaEventoDTO> listarProximosEventos(String estudanteId) {
|
||||
validarAcesso(estudanteId);
|
||||
return eventoRepositorio.findProximosEventosByEstudanteId(estudanteId, LocalDateTime.now()).stream()
|
||||
.map(this::toDTO)
|
||||
.toList();
|
||||
}
|
||||
|
||||
public RespostaEventoDTO buscarPorId(String id) {
|
||||
Evento evento = getEventoEntity(id);
|
||||
validarAcesso(evento.getEstudanteId());
|
||||
return toDTO(evento);
|
||||
}
|
||||
|
||||
public RespostaEventoDTO atualizarEvento(String id, RequisicaoEventoDTO dto) {
|
||||
Evento evento = getEventoEntity(id);
|
||||
validarAcesso(evento.getEstudanteId());
|
||||
|
||||
evento.setTitulo(dto.titulo());
|
||||
evento.setDescricao(dto.descricao());
|
||||
evento.setTipo(dto.tipo());
|
||||
evento.setLocal(dto.local());
|
||||
evento.setDataHora(dto.dataHora());
|
||||
|
||||
if (dto.disciplinaId() != null) {
|
||||
validarDisciplina(dto.disciplinaId(), evento.getEstudanteId());
|
||||
evento.setDisciplinaId(dto.disciplinaId());
|
||||
}
|
||||
|
||||
return toDTO(eventoRepositorio.save(evento));
|
||||
}
|
||||
|
||||
public void excluirEvento(String id) {
|
||||
Evento evento = getEventoEntity(id);
|
||||
validarAcesso(evento.getEstudanteId());
|
||||
eventoRepositorio.delete(evento);
|
||||
}
|
||||
|
||||
public RespostaEventoDTO cancelarEvento(String id) {
|
||||
Evento evento = getEventoEntity(id);
|
||||
validarAcesso(evento.getEstudanteId());
|
||||
evento.setStatus(Evento.StatusEvento.CANCELADO);
|
||||
return toDTO(eventoRepositorio.save(evento));
|
||||
}
|
||||
|
||||
private Evento getEventoEntity(String id) {
|
||||
return eventoRepositorio.findById(id)
|
||||
.orElseThrow(() -> new ExcecaoRecursoNaoEncontrado("Evento não encontrado"));
|
||||
}
|
||||
|
||||
private RespostaEventoDTO toDTO(Evento evento) {
|
||||
String nomeDisciplina = null;
|
||||
final String disciplinaId = evento.getDisciplinaId();
|
||||
if (disciplinaId != null) {
|
||||
var optDisciplina = disciplinaRepositorio.findById(disciplinaId);
|
||||
if (optDisciplina.isPresent()) {
|
||||
nomeDisciplina = optDisciplina.get().getNome();
|
||||
}
|
||||
}
|
||||
return new RespostaEventoDTO(
|
||||
evento.getId(),
|
||||
evento.getEstudanteId(),
|
||||
evento.getTitulo(),
|
||||
evento.getDescricao(),
|
||||
evento.getTipo() != null ? evento.getTipo().name() : null,
|
||||
evento.getLocal(),
|
||||
evento.getDisciplinaId(),
|
||||
evento.getDataHora(),
|
||||
evento.getStatus() != null ? evento.getStatus().name() : null,
|
||||
nomeDisciplina
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
package com.agendaestudantil.servico;
|
||||
|
||||
import com.agendaestudantil.entidade.Evento;
|
||||
import com.agendaestudantil.entidade.Notificacao;
|
||||
import com.agendaestudantil.entidade.Tarefa;
|
||||
import com.agendaestudantil.repositorio.EventoRepositorio;
|
||||
import com.agendaestudantil.repositorio.NotificacaoRepositorio;
|
||||
import com.agendaestudantil.repositorio.TarefaRepositorio;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class NotificacaoAgendadorServico {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(NotificacaoAgendadorServico.class);
|
||||
|
||||
private final TarefaRepositorio tarefaRepositorio;
|
||||
private final EventoRepositorio eventoRepositorio;
|
||||
private final NotificacaoRepositorio notificacaoRepositorio;
|
||||
|
||||
public NotificacaoAgendadorServico(TarefaRepositorio tarefaRepositorio, EventoRepositorio eventoRepositorio,
|
||||
NotificacaoRepositorio notificacaoRepositorio) {
|
||||
this.tarefaRepositorio = tarefaRepositorio;
|
||||
this.eventoRepositorio = eventoRepositorio;
|
||||
this.notificacaoRepositorio = notificacaoRepositorio;
|
||||
}
|
||||
|
||||
@Scheduled(fixedRate = 3600000)
|
||||
public void gerarNotificacoes() {
|
||||
log.debug("Iniciando geracao de notificacoes");
|
||||
LocalDate hoje = LocalDate.now();
|
||||
|
||||
List<Tarefa> tarefas = tarefaRepositorio.findAll();
|
||||
for (Tarefa tarefa : tarefas) {
|
||||
if (tarefa.getStatus() == Tarefa.StatusTarefa.CONCLUIDA) {
|
||||
continue;
|
||||
}
|
||||
|
||||
LocalDate dataEntrega = tarefa.getDataEntrega();
|
||||
if (dataEntrega == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
long diasAteEntrega = ChronoUnit.DAYS.between(hoje, dataEntrega);
|
||||
|
||||
if (dataEntrega.isBefore(hoje)) {
|
||||
if (!tarefa.getStatus().equals(Tarefa.StatusTarefa.ATRASADA)) {
|
||||
tarefa.setStatus(Tarefa.StatusTarefa.ATRASADA);
|
||||
tarefaRepositorio.save(tarefa);
|
||||
}
|
||||
|
||||
if (!notificacaoRepositorio.existsByEstudanteIdAndReferenciaId(tarefa.getEstudanteId(), tarefa.getId())) {
|
||||
criarNotificacao(tarefa.getEstudanteId(), tarefa.getId(),
|
||||
"Tarefa atrasada: " + tarefa.getTitulo(),
|
||||
"A tarefa '" + tarefa.getTitulo() + "' esta atrasada desde " + dataEntrega,
|
||||
Notificacao.TipoNotificacao.TAREFA_ATRASADA,
|
||||
Notificacao.TipoReferencia.TAREFA);
|
||||
}
|
||||
} else if (diasAteEntrega == 0 || diasAteEntrega == 1 || diasAteEntrega == 2 || diasAteEntrega == 3) {
|
||||
boolean enviarNotificacao = false;
|
||||
if (diasAteEntrega == 0 || diasAteEntrega == 1) {
|
||||
enviarNotificacao = true;
|
||||
} else if (diasAteEntrega == 2 || diasAteEntrega == 3) {
|
||||
if (tarefa.getPrioridade() == Tarefa.Prioridade.ALTA || tarefa.getPrioridade() == Tarefa.Prioridade.URGENTE) {
|
||||
enviarNotificacao = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (enviarNotificacao && !notificacaoRepositorio.existsByEstudanteIdAndReferenciaId(tarefa.getEstudanteId(), tarefa.getId())) {
|
||||
String prazo = diasAteEntrega == 0 ? "hoje" : (diasAteEntrega == 1 ? "amanha" : "em " + diasAteEntrega + " dias");
|
||||
criarNotificacao(tarefa.getEstudanteId(), tarefa.getId(),
|
||||
"Tarefa com prazo proximo: " + tarefa.getTitulo(),
|
||||
"A tarefa '" + tarefa.getTitulo() + "' vence " + prazo,
|
||||
Notificacao.TipoNotificacao.PRAZO_PROXIMO,
|
||||
Notificacao.TipoReferencia.TAREFA);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LocalDateTime agora = LocalDateTime.now();
|
||||
LocalDateTime em24Horas = agora.plusHours(24);
|
||||
List<Evento> eventos = eventoRepositorio.findAll();
|
||||
for (Evento evento : eventos) {
|
||||
if (evento.getDataHora() == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!evento.getDataHora().isBefore(em24Horas) && !evento.getDataHora().isAfter(em24Horas)) {
|
||||
if (!notificacaoRepositorio.existsByEstudanteIdAndReferenciaId(evento.getEstudanteId(), evento.getId())) {
|
||||
criarNotificacao(evento.getEstudanteId(), evento.getId(),
|
||||
"Evento nas proximas 24h: " + evento.getTitulo(),
|
||||
"O evento '" + evento.getTitulo() + "' sera em " + evento.getDataHora(),
|
||||
Notificacao.TipoNotificacao.EVENTO_PROXIMO,
|
||||
Notificacao.TipoReferencia.EVENTO);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.debug("Geracao de notificacoes concluida");
|
||||
}
|
||||
|
||||
private void criarNotificacao(String estudanteId, String referenciaId, String titulo, String mensagem,
|
||||
Notificacao.TipoNotificacao tipo, Notificacao.TipoReferencia tipoReferencia) {
|
||||
Notificacao notif = new Notificacao();
|
||||
notif.setEstudanteId(estudanteId);
|
||||
notif.setReferenciaId(referenciaId);
|
||||
notif.setTitulo(titulo);
|
||||
notif.setMensagem(mensagem);
|
||||
notif.setTipo(tipo);
|
||||
notif.setTipoReferencia(tipoReferencia);
|
||||
notif.setLida(false);
|
||||
notif.setDataGeracao(LocalDateTime.now());
|
||||
notificacaoRepositorio.save(notif);
|
||||
log.debug("Notificacao criada para estudante {}", estudanteId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package com.agendaestudantil.servico;
|
||||
|
||||
import com.agendaestudantil.dto.RespostaNotificacaoDTO;
|
||||
import com.agendaestudantil.entidade.Notificacao;
|
||||
import com.agendaestudantil.excecao.ExcecaoRecursoNaoEncontrado;
|
||||
import com.agendaestudantil.repositorio.NotificacaoRepositorio;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class NotificacaoServico {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(NotificacaoServico.class);
|
||||
|
||||
private final NotificacaoRepositorio notificacaoRepositorio;
|
||||
|
||||
public NotificacaoServico(NotificacaoRepositorio notificacaoRepositorio) {
|
||||
this.notificacaoRepositorio = notificacaoRepositorio;
|
||||
}
|
||||
|
||||
private void validarAcesso(String estudanteId) {
|
||||
String authUser = SecurityContextHolder.getContext().getAuthentication().getName();
|
||||
if (!authUser.equals(estudanteId)) {
|
||||
log.error("Acesso negado. Usuário {} tentou acessar recurso do estudante {}", authUser, estudanteId);
|
||||
throw new ResponseStatusException(HttpStatus.FORBIDDEN, "Acesso negado");
|
||||
}
|
||||
}
|
||||
|
||||
public List<RespostaNotificacaoDTO> listarNaoLidas(String estudanteId) {
|
||||
log.debug("Listando notificações não lidas para estudante: {}", estudanteId);
|
||||
validarAcesso(estudanteId);
|
||||
return notificacaoRepositorio.findByEstudanteIdAndLidaFalse(estudanteId).stream()
|
||||
.map(this::toDTO)
|
||||
.toList();
|
||||
}
|
||||
|
||||
public List<RespostaNotificacaoDTO> listarTodas(String estudanteId) {
|
||||
log.debug("Listando todas as notificações para estudante: {}", estudanteId);
|
||||
validarAcesso(estudanteId);
|
||||
return notificacaoRepositorio.findByEstudanteId(estudanteId).stream()
|
||||
.map(this::toDTO)
|
||||
.toList();
|
||||
}
|
||||
|
||||
public long contarNaoLidas(String estudanteId) {
|
||||
log.debug("Contando notificações não lidas para estudante: {}", estudanteId);
|
||||
validarAcesso(estudanteId);
|
||||
return notificacaoRepositorio.countByEstudanteIdAndLidaFalse(estudanteId);
|
||||
}
|
||||
|
||||
public RespostaNotificacaoDTO marcarComoLida(String id) {
|
||||
Notificacao notificacao = getNotificacaoEntity(id);
|
||||
validarAcesso(notificacao.getEstudanteId());
|
||||
notificacao.setLida(true);
|
||||
return toDTO(notificacaoRepositorio.save(notificacao));
|
||||
}
|
||||
|
||||
public void marcarTodasComoLidas(String estudanteId) {
|
||||
log.debug("Marcando todas as notificações como lidas para estudante: {}", estudanteId);
|
||||
validarAcesso(estudanteId);
|
||||
List<Notificacao> notificacoes = notificacaoRepositorio.findByEstudanteIdAndLidaFalse(estudanteId);
|
||||
for (Notificacao n : notificacoes) {
|
||||
n.setLida(true);
|
||||
notificacaoRepositorio.save(n);
|
||||
}
|
||||
}
|
||||
|
||||
public void excluirNotificacao(String id) {
|
||||
Notificacao notificacao = getNotificacaoEntity(id);
|
||||
validarAcesso(notificacao.getEstudanteId());
|
||||
notificacaoRepositorio.delete(notificacao);
|
||||
}
|
||||
|
||||
private Notificacao getNotificacaoEntity(String id) {
|
||||
return notificacaoRepositorio.findById(id)
|
||||
.orElseThrow(() -> new ExcecaoRecursoNaoEncontrado("Notificação não encontrada"));
|
||||
}
|
||||
|
||||
private RespostaNotificacaoDTO toDTO(Notificacao notificacao) {
|
||||
return new RespostaNotificacaoDTO(
|
||||
notificacao.getId(),
|
||||
notificacao.getTitulo(),
|
||||
notificacao.getMensagem(),
|
||||
notificacao.getTipo() != null ? notificacao.getTipo().name() : null,
|
||||
notificacao.getReferenciaId(),
|
||||
notificacao.getTipoReferencia() != null ? notificacao.getTipoReferencia().name() : null,
|
||||
notificacao.isLida(),
|
||||
notificacao.getDataGeracao()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
package com.agendaestudantil.servico;
|
||||
|
||||
import com.agendaestudantil.dto.RequisicaoTarefaDTO;
|
||||
import com.agendaestudantil.dto.RespostaTarefaDTO;
|
||||
import com.agendaestudantil.entidade.Tarefa;
|
||||
import com.agendaestudantil.excecao.ExcecaoRecursoNaoEncontrado;
|
||||
import com.agendaestudantil.repositorio.TarefaRepositorio;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class TarefaServico {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(TarefaServico.class);
|
||||
|
||||
private final TarefaRepositorio tarefaRepositorio;
|
||||
|
||||
public TarefaServico(TarefaRepositorio tarefaRepositorio) {
|
||||
this.tarefaRepositorio = tarefaRepositorio;
|
||||
}
|
||||
|
||||
private void validarAcesso(String estudanteId) {
|
||||
String authUser = SecurityContextHolder.getContext().getAuthentication().getName();
|
||||
if (!authUser.equals(estudanteId)) {
|
||||
log.error("Acesso negado. Usuário {} tentou acessar recurso do estudante {}", authUser, estudanteId);
|
||||
throw new ResponseStatusException(HttpStatus.FORBIDDEN, "Acesso negado");
|
||||
}
|
||||
}
|
||||
|
||||
private void validarAcessoTarefa(Tarefa tarefa) {
|
||||
validarAcesso(tarefa.getEstudanteId());
|
||||
}
|
||||
|
||||
public RespostaTarefaDTO criarTarefa(RequisicaoTarefaDTO dto) {
|
||||
String estudanteId = SecurityContextHolder.getContext().getAuthentication().getName();
|
||||
log.debug("Criando tarefa para estudante: {}", estudanteId);
|
||||
|
||||
Tarefa tarefa = new Tarefa();
|
||||
tarefa.setTitulo(dto.titulo());
|
||||
tarefa.setDescricao(dto.descricao());
|
||||
tarefa.setPrioridade(dto.prioridade() != null ? dto.prioridade() : Tarefa.Prioridade.MEDIA);
|
||||
tarefa.setStatus(dto.status() != null ? dto.status() : Tarefa.StatusTarefa.PENDENTE);
|
||||
tarefa.setDataEntrega(dto.dataEntrega());
|
||||
tarefa.setEstudanteId(estudanteId);
|
||||
|
||||
if (dto.disciplinaId() != null) {
|
||||
tarefa.setDisciplinaId(dto.disciplinaId());
|
||||
}
|
||||
|
||||
return toDTO(tarefaRepositorio.save(tarefa));
|
||||
}
|
||||
|
||||
public List<RespostaTarefaDTO> listarTarefasPorEstudante(String estudanteId) {
|
||||
log.debug("Listando tarefas para estudante: {}", estudanteId);
|
||||
validarAcesso(estudanteId);
|
||||
return tarefaRepositorio.findByEstudanteId(estudanteId).stream()
|
||||
.map(this::toDTO)
|
||||
.toList();
|
||||
}
|
||||
|
||||
public List<RespostaTarefaDTO> listarTarefasPendentes(String estudanteId) {
|
||||
log.debug("Listando tarefas pendentes para estudante: {}", estudanteId);
|
||||
validarAcesso(estudanteId);
|
||||
return tarefaRepositorio.findByEstudanteIdAndStatus(estudanteId, Tarefa.StatusTarefa.PENDENTE).stream()
|
||||
.map(this::toDTO)
|
||||
.toList();
|
||||
}
|
||||
|
||||
public List<RespostaTarefaDTO> listarTarefasPorData(String estudanteId, LocalDate data) {
|
||||
validarAcesso(estudanteId);
|
||||
return tarefaRepositorio.findByEstudanteIdAndDataEntrega(estudanteId, data).stream()
|
||||
.map(this::toDTO)
|
||||
.toList();
|
||||
}
|
||||
|
||||
public List<RespostaTarefaDTO> listarTarefasPorPeriodo(String estudanteId, LocalDate inicio, LocalDate fim) {
|
||||
validarAcesso(estudanteId);
|
||||
return tarefaRepositorio.findByEstudanteIdAndDataEntregaBetween(estudanteId, inicio, fim).stream()
|
||||
.map(this::toDTO)
|
||||
.toList();
|
||||
}
|
||||
|
||||
public RespostaTarefaDTO buscarTarefaPorId(String id) {
|
||||
return toDTO(getTarefaEntity(id));
|
||||
}
|
||||
|
||||
public RespostaTarefaDTO atualizarTarefa(String id, RequisicaoTarefaDTO dto) {
|
||||
Tarefa tarefa = getTarefaEntity(id);
|
||||
String authUser = SecurityContextHolder.getContext().getAuthentication().getName();
|
||||
if (!authUser.equals(tarefa.getEstudanteId())) {
|
||||
throw new ResponseStatusException(HttpStatus.FORBIDDEN, "Acesso negado");
|
||||
}
|
||||
|
||||
tarefa.setTitulo(dto.titulo());
|
||||
tarefa.setDescricao(dto.descricao());
|
||||
tarefa.setPrioridade(dto.prioridade() != null ? dto.prioridade() : tarefa.getPrioridade());
|
||||
tarefa.setStatus(dto.status() != null ? dto.status() : tarefa.getStatus());
|
||||
if (dto.dataEntrega() != null) {
|
||||
tarefa.setDataEntrega(dto.dataEntrega());
|
||||
}
|
||||
|
||||
if (dto.disciplinaId() != null) {
|
||||
tarefa.setDisciplinaId(dto.disciplinaId());
|
||||
}
|
||||
|
||||
return toDTO(tarefaRepositorio.save(tarefa));
|
||||
}
|
||||
|
||||
public void excluirTarefa(String id) {
|
||||
tarefaRepositorio.delete(getTarefaEntity(id));
|
||||
}
|
||||
|
||||
public RespostaTarefaDTO marcarConcluida(String id) {
|
||||
Tarefa tarefa = getTarefaEntity(id);
|
||||
tarefa.setStatus(Tarefa.StatusTarefa.CONCLUIDA);
|
||||
return toDTO(tarefaRepositorio.save(tarefa));
|
||||
}
|
||||
|
||||
private Tarefa getTarefaEntity(String id) {
|
||||
Tarefa tarefa = tarefaRepositorio.findById(id)
|
||||
.orElseThrow(() -> new ExcecaoRecursoNaoEncontrado("Tarefa não encontrada"));
|
||||
validarAcessoTarefa(tarefa);
|
||||
return tarefa;
|
||||
}
|
||||
|
||||
private RespostaTarefaDTO toDTO(Tarefa tarefa) {
|
||||
return new RespostaTarefaDTO(
|
||||
tarefa.getId(),
|
||||
tarefa.getTitulo(),
|
||||
tarefa.getDescricao(),
|
||||
tarefa.getPrioridade() != null ? tarefa.getPrioridade().name() : null,
|
||||
tarefa.getStatus() != null ? tarefa.getStatus().name() : null,
|
||||
tarefa.getDataEntrega(),
|
||||
tarefa.getDisciplinaId(),
|
||||
tarefa.getEstudanteId());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.agendaestudantil.utilitario;
|
||||
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.security.Keys;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Date;
|
||||
|
||||
@Component
|
||||
public class UtilJwt {
|
||||
|
||||
private final String secret;
|
||||
private final long jwtExpiration;
|
||||
|
||||
public UtilJwt(@Value("${jwt.secret}") String secret, @Value("${jwt.expiration}") long jwtExpiration) {
|
||||
this.secret = secret;
|
||||
this.jwtExpiration = jwtExpiration;
|
||||
}
|
||||
|
||||
private SecretKey getSigningKey() {
|
||||
return Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
public String generateToken(String estudanteId) {
|
||||
Date now = new Date();
|
||||
Date expiryDate = new Date(now.getTime() + jwtExpiration);
|
||||
|
||||
return Jwts.builder()
|
||||
.subject(estudanteId)
|
||||
.issuedAt(now)
|
||||
.expiration(expiryDate)
|
||||
.signWith(getSigningKey())
|
||||
.compact();
|
||||
}
|
||||
|
||||
public String getEstudanteIdFromToken(String token) {
|
||||
Claims claims = Jwts.parser()
|
||||
.verifyWith(getSigningKey())
|
||||
.build()
|
||||
.parseSignedClaims(token)
|
||||
.getPayload();
|
||||
|
||||
return claims.getSubject();
|
||||
}
|
||||
|
||||
public boolean validateToken(String token) {
|
||||
try {
|
||||
Jwts.parser().verifyWith(getSigningKey()).build().parseSignedClaims(token);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user