Projeto final desenvolvido para o curso avançado de programação da Lions (Dez/2025).
Este projeto consiste em uma aplicação completa de autenticação e gerenciamento de usuários, desenvolvida para demonstrar a integração entre um front-end low-code e uma API robusta desenvolvida manualmente.
O objetivo foi criar uma página de criar e logar usuários, onde a interface foi construída no FlutterFlow e toda a regra de negócio e persistência de dados reside em uma API RESTful personalizada.
Projeto apresentado como requisito final do curso avançado de programação (2025), com foco em desenvolvimento de APIs e integração de sistemas.
A aplicação segue a arquitetura Cliente-Servidor com separação clara de responsabilidades:
- Front-end (Mobile/Web): FlutterFlow - Responsável pela UI/UX e requisições HTTP
- Back-end (API): Node.js + Express - Servidor RESTful com arquitetura em camadas
- Banco de Dados: MongoDB (via Mongoose) - Persistência de dados NoSQL
- Autenticação: JWT (JSON Web Tokens) - Autenticação stateless
- Segurança: Bcrypt - Criptografia de senhas com hash
O backend segue o padrão de arquitetura em camadas (Layered Architecture):
backend/
├── src/
│ ├── config/ # Configurações (DB, etc)
│ ├── controllers/ # Controladores (recebem requisições)
│ ├── services/ # Lógica de negócio
│ ├── repositories/ # Acesso ao banco de dados
│ ├── models/ # Schemas do MongoDB
│ ├── middlewares/ # Validações e autenticação
│ ├── routes/ # Definição de rotas
│ ├── utils/ # Utilitários (tratamento de erros)
│ ├── app.js # Configuração do Express
│ └── server.js # Inicialização do servidor
Explicação das Camadas:
- Routes → Define os endpoints e aplica middlewares
- Controllers → Recebe requisições HTTP, chama services e retorna respostas
- Services → Contém a lógica de negócio (validações, criptografia, geração de tokens)
- Repositories → Faz a comunicação direta com o banco de dados
- Models → Define o schema/estrutura dos dados no MongoDB
- Middlewares → Validações, autenticação e tratamento de erros
- Cliente (FlutterFlow) envia requisição HTTP para a API
- Route recebe e encaminha para o Controller
- Controller chama o Service correspondente
- Service aplica regras de negócio e chama o Repository
- Repository consulta/modifica o MongoDB
- Resposta retorna pela mesma cadeia até o cliente
- ✅ Criar Usuário (Registro): Cadastro com nome, email e senha (criptografada com bcrypt)
- ✅ Login: Autenticação com validação de credenciais e geração de token JWT
- ✅ Listar Usuários: Retorna todos os usuários cadastrados (requer role ADMIN)
- ✅ Buscar Usuário por ID: Retorna dados de um usuário específico
- ✅ Atualizar Usuário: Atualiza informações de um usuário
- ✅ Deletar Usuário: Remove usuário do sistema (requer role ADMIN)
- ✅ Hello (Autenticado): Rota protegida que retorna o ID do usuário logado
- 🔒 Senhas criptografadas com bcrypt (12 rounds)
- 🔒 Autenticação via JWT tokens com expiração de 1 hora
- 🔒 RBAC (Role-Based Access Control): Controle de acesso baseado em roles (USER/ADMIN)
- 🔒 Middleware de autenticação protege rotas sensíveis
- 🔒 Middleware de autorização verifica permissões por role
- 🔒 Validação de entrada de dados
- 🔒 Tratamento centralizado de erros
Base URL: http://localhost:2323/api
| Método | Endpoint | Descrição | Body |
|---|---|---|---|
POST |
/api/users |
Cria um novo usuário | { "name": "string", "email": "string", "password": "string", "roles": "string" } |
POST |
/api/users/login |
Faz login e retorna token JWT | { "email": "string", "password": "string" } |
GET |
/api/users/:id |
Busca usuário por ID | - |
PUT |
/api/users/:id |
Atualiza usuário | { "name": "string", "email": "string", "roles": "string" } |
| Método | Endpoint | Descrição | Role Necessária | Headers |
|--------|----------|-----------|----------------|---------|------|
| GET | /api/users/hello | Retorna ID do usuário autenticado | Qualquer | Authorization: Bearer {token} |
| Método | Endpoint | Descrição | Headers |
|--------|----------|-----------|---------|------|
| GET | /api/users | Lista todos os usuários | Authorization: Bearer {token} |
| DELETE | /api/users/:id | Remove usuário do sistema | Authorization: Bearer {token} |
1. Criar Usuário
POST /api/users
Content-Type: application/json
{
"name": "João Silva",
"email": "joao@email.com",
"password": "senha123",
"roles": "USER"
}Resposta:
{
"id": "67...",
"name": "João Silva",
"email": "joao@email.com",
"roles": "USER"
}2. Login
POST /api/users/login
Content-Type: application/json
{
"email": "joao@email.com",
"password": "senha123"
}Resposta:
{
"message": "Seu ID é 67...",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"id": "67...",
"name": "João Silva",
"email": "joao@email.com",
"roles": "USER"
}
}3. Rota Protegida (Hello)
GET /api/users/hello
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...Resposta:
{
"message": "Seu ID é 67..."
}- Node.js v16+ instalado
- MongoDB rodando (local ou cloud - MongoDB Atlas)
- Git para clonar o repositório
- Postman ou similar para testar a API
- Clone o repositório:
git clone https://github.com/LucasSassi/final_project_lions.git
cd final_project_lions/backend- Instale as dependências:
npm install- Configure as variáveis de ambiente:
Crie um arquivo .env na pasta backend/ com:
MONGODB_URI=mongodb://localhost:27017/lions_dev
JWT_SECRET=sua_chave_secreta_super_segura- Inicie o servidor:
npm start
# ou para desenvolvimento com hot-reload:
npm run dev- Teste a API:
- API rodando em:
http://localhost:2323 - Teste:
GET http://localhost:2323/api/test
Testando Rotas Públicas:
- Criar usuário comum (USER):
POST /api/users
{
"name": "João Silva",
"email": "joao@email.com",
"password": "senha123",
"roles": "USER"
}
- Criar usuário administrador (ADMIN):
POST /api/users
{
"name": "Admin Master",
"email": "admin@email.com",
"password": "admin123",
"roles": "ADMIN"
}
Testando Autenticação:
- Fazer login:
POST /api/users/login
{
"email": "admin@email.com",
"password": "admin123"
}
- Copie o token retornado e adicione nas próximas requisições:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Testando Rotas Protegidas:
- Testar rota autenticada (qualquer usuário logado):
GET /api/users/hello
Authorization: Bearer {seu_token}
- Testar rota ADMIN (apenas com token de ADMIN):
GET /api/users
Authorization: Bearer {token_do_admin}
- Tentar acessar rota ADMIN com usuário USER (deve dar 403):
GET /api/users
Authorization: Bearer {token_do_user}
// Resposta: { "error": "Acesso negado. Requer role: ADMIN" }
- Deletar usuário (apenas ADMIN):
DELETE /api/users/{id}
Authorization: Bearer {token_do_admin}
// Resposta: { "message": "Usuário removido com sucesso." }
// Controller recebe a requisição
async create(req, res, next) {
const user = await userService.createUser(req.body);
res.status(201).json(user);
}
// Service valida e processa
async createUser(data) {
ensureValidPayload(data); // Valida email, nome, senha
const existing = await repo.findByEmail(data.email); // Verifica se já existe
if (existing) throw createError("E-mail já cadastrado.", 409);
const senhaHash = await bcrypt.hash(data.password, 12); // Criptografa
return repo.create({ ...data, password: senhaHash }); // Salva no DB
}// Verifica credenciais e gera token
async loginUsers({ email, password }) {
const user = await repo.findByEmail(email);
if (!user) throw createError("Credenciais inválidas.", 401);
const senhaValida = await bcrypt.compare(password, user.password);
if (!senhaValida) throw createError("Credenciais inválidas.", 401);
// Gera token JWT válido por 1 hora
const token = jwt.sign(
{ userId: user._id, roles: user.roles },
process.env.JWT_SECRET,
{ expiresIn: "1h" }
);
return { message: `Seu ID é ${user._id}`, token, user };
}// Protege rotas verificando o token
export function authMiddleware() {
return (req, res, next) => {
const token = req.headers.authorization?.slice(7); // Remove "Bearer "
if (!token) throw createError("Token não informado.", 401);
req.user = jwt.verify(token, process.env.JWT_SECRET); // Valida token
next(); // Permite acesso à rota
};
}
// Verifica se o usuário tem a role necessária
export function requireRole(...allowedRoles) {
return (req, res, next) => {
if (!req.user) throw createError("Usuário não autenticado.", 401);
const userRoles = Array.isArray(req.user.roles)
? req.user.roles
: [req.user.roles];
const hasPermission = allowedRoles.some(role => userRoles.includes(role));
if (!hasPermission) {
throw createError("Acesso negado. Requer role: " + allowedRoles.join(", "), 403);
}
next();
};
}
// Uso nas rotas
router.get("/users", authMiddleware(), requireRole(Role.ADMIN), userController.list);// Middleware centralizado captura todos os erros
export default function errorMiddleware(error, req, res, next) {
const statusCode = error.statusCode || 500;
const message = error.message || "Erro interno do servidor";
res.status(statusCode).json({ error: message });
}- REST API - Padrão de arquitetura para APIs web
- CRUD - Create, Read, Update, Delete
- JWT - Autenticação stateless com tokens
- RBAC - Role-Based Access Control (controle de acesso baseado em papéis)
- Bcrypt - Hashing seguro de senhas
- Middleware - Interceptadores de requisições
- Arquitetura em Camadas - Separação de responsabilidades
- MongoDB - Banco de dados NoSQL
- Mongoose - ODM (Object Document Mapper)
- Async/Await - Programação assíncrona moderna
- Error Handling - Tratamento centralizado de erros
- Authorization vs Authentication - Autenticação (quem é) vs Autorização (o que pode fazer)
Lucas Sassi
- GitHub: @LucasSassi
- Projeto: Lions Dev - Curso Avançado de Programação (2025)
ISC License - Este projeto foi desenvolvido para fins educacionais.