Arquitetrua do Sistema e Papéis dos Usuários
O sistema é projetado para atender às necessidades de saúde comunitária, com três grupos de usuários principais: residentes comunitários, profissionais médicos e administradores. A arquitetura segue o modelo B/S (Navegador/Servidor), garantindo acessibilidade multiplataforma e fácil manutenção. A separação entre frontend e backend permite desenvolvimento independente, com comunicação baseada em HTTP/REST.
Pilha Tecnológica
Frontend: Vue.js
Vue.js é um framework progressivo para construção de interfaces de usuário. Sua reatividade baseada em proxies simplifica a sincronização de dados com o DOM. O sistema de componentes, com arquivos únicos (.vue), facilita a modularidade. Vuex é utilizado para gerenciamento de estado global, e Vue Router para navegação em aplicações de página única (SPA), proporcionando uma experiência fluida.
Backend: Spring Boot
Spring Boot acelera o desenvolvimento de aplicações Spring ao fornecer autoconfiguração e dependências via "Starters". Integra-se com Spring Data JPA para acesso a dados e Spring Security para autenticação. O módulo Actuator permite monitoramento em tempo real de métricas e saúde da aplicação, essencial para ambientes de produção.
Banco de Dados: MySQL
MySQL é um sistema de gerenciamento de banco de dados relacional (RDBMS) de código aberto, otimizado para consultas de alto desempenho. Suporta transações ACID, indexação avançada e uma variedade de tipos de dados. É utilizado para armazenar informações de usuários, registros de saúde e dados operacionais do sistema.
Testes do Sistema
Metodologia de Testes
Os testes foram conduzidos utilizando abordagem de caixa preta, focando na validação de funcionalidades a partir da perspectiva do usuário. Casos de teste foram projetados para cobrir fluxos comuns, garantindo que o sistema atenda aos requisitos de usabilidade e robustez.
Casos de Teste para Residentes
| ID | Funcionalidade | Cenário | Resultado Esperado | Resultado Obtido | Status |
|---|---|---|---|---|---|
| T1 | Cadastro de Usuário | Preencher formulário com dados válidos | Cadastro concluído com sucesso | Cadastro concluído | Aprovado |
| T2 | Autenticação | Inserir credecniais corretas | Login efetuado | Login efetuado | Aprovado |
| T3 | Agendamento de Consultas | Selecionar horário e confirmar | Agendamento registrado | Agendamento registrado | Aprovado |
| T4 | Acesso a Registros | Visualizar histórico médico | Dados exibidos corretamente | Dados exibidos | Aprovado |
Casos de Teste para Administradores
| ID | Funcionalidade | Cenário | Resultado Esperado | Resultado Obtido | Status |
|---|---|---|---|---|---|
| T5 | Gerenciamento de Usuários | Buscar usuário por nome | Registro encontrado | Registro encontrado | Aprovado |
| T6 | Publicação de Comunicados | Criar novo aviso com conteúdo | Comunicado publicado | Comunicado publicado | Aprovado |
| T7 | Moderação de Conteúdo | Editar informações de saúde | Alterações salvas | Alterações salvas | Aprovado |
Exemplos de Código
Autenticação e Geração de Token (Spring Boot)
@RestController
@RequestMapping("/auth")
public class AuthController {
@Autowired
private UserService userService;
@Autowired
private TokenGenerator tokenGenerator;
@PostMapping("/login")
public ResponseEntity<?> authenticateUser(@RequestBody LoginRequest request) {
Optional<User> user = userService.findByEmail(request.getEmail());
if (user.isPresent() && passwordEncoder.matches(request.getSenha(), user.get().getSenhaHash())) {
String jwtToken = tokenGenerator.createToken(user.get().getId(), user.get().getPapel());
return ResponseEntity.ok(new TokenResponse(jwtToken));
}
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Credenciais inválidas");
}
}
@Service
public class TokenGenerator {
@Value("${jwt.secret}")
private String secretKey;
public String createToken(Long userId, String papel) {
Date expiryDate = Date.from(Instant.now().plus(1, ChronoUnit.HOURS));
return Jwts.builder()
.setSubject(userId.toString())
.claim("papel", papel)
.setExpiration(expiryDate)
.signWith(SignatureAlgorithm.HS256, secretKey)
.compact();
}
}
Interceptor de Autorização
@Component
public class AuthInterceptor implements HandlerInterceptor {
private static final String AUTH_HEADER = "Authorization";
@Autowired
private TokenValidator tokenValidator;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
if (request.getMethod().equalsIgnoreCase("OPTIONS")) {
return true;
}
String authHeader = request.getHeader(AUTH_HEADER);
if (authHeader != null && authHeader.startsWith("Bearer ")) {
String token = authHeader.substring(7);
Claims claims = tokenValidator.validateToken(token);
if (claims != null) {
request.setAttribute("userId", claims.getSubject());
request.setAttribute("userRole", claims.get("papel", String.class));
return true;
}
}
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
return false;
}
}
Esquema do Banco de Dados (Exemplo Parcial)
CREATE DATABASE IF NOT EXISTS saude_comunitaria CHARACTER SET utf8mb4;
USE saude_comunitaria;
CREATE TABLE usuarios (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
nome_completo VARCHAR(100) NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
senha_hash VARCHAR(255) NOT NULL,
papel ENUM('residente', 'medico', 'admin') NOT NULL,
criado_em TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE registros_medicos (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
usuario_id BIGINT NOT NULL,
descricao TEXT,
data_registro DATE,
FOREIGN KEY (usuario_id) REFERENCES usuarios(id) ON DELETE CASCADE
);