Arquitetura e Visão Geral do Sistema
O desenvolvimento de plataformas para coordenação de voluntariado exige uma arquitetura escalável, segura e de fácil manutenção. A solução proposta adota o modelo B/S (Browser/Server), separando claramente a camada de apresentação da lógica de negócios. O frontend é construído com Vue.js, garantindo uma interface reativa e modular, enquanto o backend utiliza Spring Boot para expor APIs RESTful padronizadas. O armazenamento de dados é gerenciado pelo MySQL, assegurando integridade relacional e desempenho otimizado em consultas concorrentes.
Implementação do Backend com Spring Boot
O núcleo da aplicação backend segue o princípio de convenção sobre configuração, eliminando a necessidade de arquivos XML extensos e acelerando a inicialização do contexto. A autenticação é baseada em tokens stateless, onde cada requisição válida carrega um identificador de sessão com tempo de vida limitado. O controlador de acesso valida as credenciais recebidas, delega a geração do token a um serviço dedicado e reetorna o identificador ao cliente. Um interceptador global verifica a presença e a validade desse token antes de liberar o acesso aos endpoints protegidos, aplicando políticas de CORS e tratando métodos OPTIONS automaticamente.
Controlador de Autenticação
@RestController
@RequestMapping("/api/auth")
public class AuthController {
private final VolunteerService volunteerService;
private final TokenManager tokenManager;
public AuthController(VolunteerService volunteerService, TokenManager tokenManager) {
this.volunteerService = volunteerService;
this.tokenManager = tokenManager;
}
@PostMapping("/signin")
public ResponseEntity<Map<String, Object>> authenticate(@RequestBody LoginRequest credentials) {
VolunteerEntity account = volunteerService.findByEmail(credentials.getEmail());
if (account == null || !account.getPasswordHash().equals(credentials.getPassword())) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
.body(Map.of("error", "Credenciais inválidas ou conta inexistente."));
}
String sessionToken = tokenManager.createSession(account.getId(), account.getRole());
return ResponseEntity.ok(Map.of("accessToken", sessionToken));
}
}
Interceptador de Validação de Sessão
@Component
public class SessionValidator implements HandlerInterceptor {
private static final String AUTH_HEADER = "X-Session-Token";
private final TokenRepository tokenRepository;
public SessionValidator(TokenRepository tokenRepository) {
this.tokenRepository = tokenRepository;
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (request.getMethod().equals("OPTIONS")) {
response.setStatus(HttpServletResponse.SC_OK);
return false;
}
if (handler instanceof HandlerMethod method) {
if (method.hasMethodAnnotation(PublicEndpoint.class)) {
return true;
}
}
String token = request.getHeader(AUTH_HEADER);
if (token == null || token.isBlank()) {
sendUnauthorized(response);
return false;
}
SessionRecord record = tokenRepository.findByTokenValue(token);
if (record == null || record.getExpiresAt().before(new Date())) {
sendUnauthorized(response);
return false;
}
request.setAttribute("currentUserId", record.getUserId());
request.setAttribute("currentUserRole", record.getRole());
return true;
}
private void sendUnauthorized(HttpServletResponse res) throws IOException {
res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
res.setContentType("application/json;charset=UTF-8");
res.getWriter().write("{\"message\": \"Acesso negado. Autenticação necessária.\"}");
}
}
Desenvolvimento Frontend com Vue.js
A camada de apresentação utiliza Vue 3 com a Composition API, facilitando a organização lógica por funcionalidade e melhorando a reutilização de código entre componentes. O roteamento é gerenciado pelo Vue Router, protegendo rotas administrativas através de navigation guards que verificam a existência e a validade do token armazenado. O estado global, como informações do usuário autenticado, listas de campanhas ativas e notificações, é centralizado via Pinia, substituindo abordagens mais verbosas e garantindo sincronização reativa em toda a árvore de componentes.
Modelagem de Dados e Estrutura Relacional
O banco de dados MySQL foi normalizado para evitar redundância e garantir consistência nas operações de recrutamento. As tabelas principais incluem registros de voluntários, campanhas disponíveis, inscrições e configurações globais. Índices compostos são aplicados em colunas frequentemente filtradas, como status de inscrição e datas de campanha, otimizando o tempo de resposta das consultas e reduzindo a carga no servidor de aplicação.
Script de Criação de Tabelas Essenciais
CREATE DATABASE IF NOT EXISTS volunteer_hub DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE volunteer_hub;
CREATE TABLE volunteers (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
full_name VARCHAR(150) NOT NULL,
email VARCHAR(120) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
role ENUM('ADMIN', 'VOLUNTEER') DEFAULT 'VOLUNTEER',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB;
CREATE TABLE campaigns (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(200) NOT NULL,
description TEXT,
start_date DATE NOT NULL,
end_date DATE NOT NULL,
status ENUM('OPEN', 'CLOSED', 'DRAFT') DEFAULT 'DRAFT',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB;
CREATE TABLE applications (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
volunteer_id BIGINT NOT NULL,
campaign_id BIGINT NOT NULL,
applied_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
status ENUM('PENDING', 'APPROVED', 'REJECTED') DEFAULT 'PENDING',
FOREIGN KEY (volunteer_id) REFERENCES volunteers(id) ON DELETE CASCADE,
FOREIGN KEY (campaign_id) REFERENCES campaigns(id) ON DELETE CASCADE,
UNIQUE KEY unique_application (volunteer_id, campaign_id)
) ENGINE=InnoDB;
Validação Funcional e Cenários de Teste
A garantia de qualidade foi realizada através de testes de caixa preta, simulando interações reais de usuários e administradores. Cada módulo foi isolado para verificar se as saídas correspondem aos requisitos especificados. A tabela abaixo resume os casos de teste executados na interface do voluntário.
| Código | Funcionalidade | Ação Executada | Resultado Esperado | Status |
|---|---|---|---|---|
| T-01 | Cadastro | Preencher formulário com dados válidos | Conta criada e redirecionamento | Aprovado |
| T-02 | Autenticação | Inserir e-mail e senha corretos | Geração de token e acesso ao painel | Aprovado |
| T-03 | Inscrição em Campanha | Clicar em "Participar" em campanha aberta | Registro salvo com status PENDENTE | Aprovado |
| T-04 | Consulta de Histórico | Acessar aba "Minhas Inscrições" | Lista filtrada por usuário exibida | Aprovado |
Para o painel administrativo, os testes focaram na gestão de campanhas e moderação de inscrições. A validação confirmou que a criação, edição e remoção de registros atualizam coretamente o banco de dados e refletem imediatamente na interface, sem inconsistências de estado. A abordagem de testes contínuos durante o ciclo de desenvolvimento permitiu a identificação precoce de gargalos de desempenho e falhas de validação de entrada, resultando em uma aplicação estável e alinhada aos requisitos operacionais de recrutamento.