Enviar arquivos para "/"
This commit is contained in:
79
authMiddleware.js
Normal file
79
authMiddleware.js
Normal file
@@ -0,0 +1,79 @@
|
||||
// filepath: config/authMiddleware.js
|
||||
const jwt = require('jsonwebtoken');
|
||||
const crypto = require('crypto');
|
||||
|
||||
// Middleware para validar o token JWT nas requisições
|
||||
const authenticateToken = (req, res, next) => {
|
||||
// Pega o token do header Authorization
|
||||
const authHeader = req.headers['authorization'];
|
||||
const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN
|
||||
|
||||
if (!token) {
|
||||
return res.status(401).json({
|
||||
error: 'Acesso negado. Token não fornecido.'
|
||||
});
|
||||
}
|
||||
|
||||
// Decodifica o token sem verificar para detectar o algoritmo
|
||||
const decoded = jwt.decode(token, { complete: true });
|
||||
const algorithm = decoded?.header?.alg || 'HS256';
|
||||
|
||||
// Converte a chave pública PEM de string multilinha para formato de linha única
|
||||
const publicKeyPEM = process.env.JWT_PUBLIC_KEY_PEM
|
||||
? process.env.JWT_PUBLIC_KEY_PEM.replace(/\\n/g, '\n')
|
||||
: null;
|
||||
|
||||
// Opções de verificação do token
|
||||
const verifyOptions = {
|
||||
issuer: process.env.JWT_ISSUER,
|
||||
audience: process.env.JWT_AUDIENCE,
|
||||
};
|
||||
|
||||
// Detecta o algoritmo e usa a chave correta
|
||||
if (algorithm === 'RS256' || algorithm === 'RS384' || algorithm === 'RS512') {
|
||||
// Usa chave pública para RS256
|
||||
if (!publicKeyPEM) {
|
||||
return res.status(500).json({
|
||||
error: 'Configuração erro: chave pública não configurada.'
|
||||
});
|
||||
}
|
||||
verifyOptions.algorithms = ['RS256'];
|
||||
jwt.verify(token, publicKeyPEM, verifyOptions, (err, user) => {
|
||||
if (err) {
|
||||
return res.status(403).json({
|
||||
error: 'Token inválido ou expirado.',
|
||||
details: err.message
|
||||
});
|
||||
}
|
||||
// Define req.auth com id do payload e o token
|
||||
req.auth = {
|
||||
id: user.sub || user.id,
|
||||
token
|
||||
};
|
||||
next();
|
||||
});
|
||||
} else if (algorithm === 'HS256' || algorithm === 'HS384' || algorithm === 'HS512') {
|
||||
// Usa JWT_SECRET para HS256
|
||||
verifyOptions.algorithms = ['HS256'];
|
||||
jwt.verify(token, process.env.JWT_SECRET, verifyOptions, (err, user) => {
|
||||
if (err) {
|
||||
return res.status(403).json({
|
||||
error: 'Token inválido ou expirado.',
|
||||
details: err.message
|
||||
});
|
||||
}
|
||||
// Define req.auth com id do payload e o token
|
||||
req.auth = {
|
||||
id: user.sub || user.id,
|
||||
token
|
||||
};
|
||||
next();
|
||||
});
|
||||
} else {
|
||||
return res.status(400).json({
|
||||
error: 'Algoritmo não suportado: ' + algorithm
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = { authenticateToken };
|
||||
48
db.js
48
db.js
@@ -1,24 +1,24 @@
|
||||
const mysql = require('mysql2');
|
||||
|
||||
// Aqui está a configuração da nossa conexão com o banco de dados!
|
||||
// Cada microsserviço tem seu próprio banco, lembra? Isso garante independência.
|
||||
// Estou usando MySQL porque é confiável e funciona bem com Node.js.
|
||||
const connection = mysql.createConnection({
|
||||
host: 'localhost', // O banco roda na mesma máquina
|
||||
user: 'root', // Usuário padrão do MySQL
|
||||
password: '', // Sem senha para desenvolvimento local
|
||||
database: 'gameverse_library' // Nosso banco exclusivo da biblioteca
|
||||
});
|
||||
|
||||
// Esta função tenta conectar ao banco quando o serviço inicia.
|
||||
// Se der erro, a gente sabe que tem problema na configuração do MySQL.
|
||||
connection.connect((err) => {
|
||||
if (err) {
|
||||
console.error('Erro ao conectar:', err);
|
||||
return;
|
||||
}
|
||||
console.log('Banco conectado!');
|
||||
});
|
||||
|
||||
// Exportamos a conexão para usar em outros arquivos, principalmente no model.
|
||||
module.exports = connection;
|
||||
const mysql = require('mysql2');
|
||||
|
||||
// Aqui está a configuração da nossa conexão com o banco de dados!
|
||||
// Cada microsserviço tem seu próprio banco, lembra? Isso garante independência.
|
||||
// Estou usando MySQL porque é confiável e funciona bem com Node.js.
|
||||
const connection = mysql.createConnection({
|
||||
host: 'localhost', // O banco roda na mesma máquina
|
||||
user: 'root', // Usuário padrão do MySQL
|
||||
password: '', // Sem senha para desenvolvimento local
|
||||
database: 'gameverse_library' // Nosso banco exclusivo da biblioteca
|
||||
});
|
||||
|
||||
// Esta função tenta conectar ao banco quando o serviço inicia.
|
||||
// Se der erro, a gente sabe que tem problema na configuração do MySQL.
|
||||
connection.connect((err) => {
|
||||
if (err) {
|
||||
console.error('Erro ao conectar:', err);
|
||||
return;
|
||||
}
|
||||
console.log('Banco conectado!');
|
||||
});
|
||||
|
||||
// Exportamos a conexão para usar em outros arquivos, principalmente no model.
|
||||
module.exports = connection;
|
||||
|
||||
@@ -1,127 +1,131 @@
|
||||
const model = require('../models/libraryModel');
|
||||
|
||||
// Este é o "cérebro" do nosso microsserviço!
|
||||
// O controller recebe as requisições HTTP, valida os dados,
|
||||
// chama as funções do model e retorna respostas apropriadas.
|
||||
// É como o gerente que coordena tudo.
|
||||
|
||||
// Função para adicionar um item manualmente à biblioteca.
|
||||
// Pode ser usado para correções ou imports especiais.
|
||||
exports.addItem = (req, res) => {
|
||||
// Validação básica dos dados obrigatórios
|
||||
const { user_id, type, item_id, title } = req.body;
|
||||
|
||||
if (!user_id || !type || !item_id || !title) {
|
||||
return res.json({
|
||||
success: false,
|
||||
message: 'Dados obrigatórios faltando: user_id, type, item_id, title'
|
||||
});
|
||||
}
|
||||
|
||||
// Só aceitamos tipos válidos para manter consistência
|
||||
if (!['game', 'gift_card'].includes(type)) {
|
||||
return res.json({
|
||||
success: false,
|
||||
message: 'Tipo inválido. Use "game" ou "gift_card"'
|
||||
});
|
||||
}
|
||||
|
||||
// Chama o model para adicionar o item
|
||||
model.addItem(req.body, (err) => {
|
||||
if (err) {
|
||||
return res.json({
|
||||
success: false,
|
||||
error: err,
|
||||
message: 'Erro ao adicionar item à biblioteca'
|
||||
});
|
||||
}
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: 'Item adicionado à biblioteca com sucesso!'
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// Função que retorna toda a biblioteca de um usuário.
|
||||
// É chamada quando o usuário abre sua página de biblioteca.
|
||||
exports.getLibrary = (req, res) => {
|
||||
const user_id = req.params.user_id;
|
||||
|
||||
// Validação do ID do usuário
|
||||
if (!user_id || isNaN(user_id)) {
|
||||
return res.json({
|
||||
success: false,
|
||||
message: 'ID do usuário inválido'
|
||||
});
|
||||
}
|
||||
|
||||
// Busca todos os itens do usuário
|
||||
model.getUserLibrary(user_id, (err, results) => {
|
||||
if (err) {
|
||||
return res.json({
|
||||
success: false,
|
||||
error: err,
|
||||
message: 'Erro ao buscar biblioteca'
|
||||
});
|
||||
}
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: results,
|
||||
message: `Encontrados ${results.length} itens na biblioteca`
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// Esta é a função mais importante para integração!
|
||||
// É chamada AUTOMATICAMENTE pelo serviço de pagamentos quando uma compra é aprovada.
|
||||
// Garante que o usuário receba seu jogo/gift card na biblioteca.
|
||||
exports.paymentApproved = (req, res) => {
|
||||
const data = req.body;
|
||||
|
||||
// Validações rigorosas pois isso vem de outro serviço
|
||||
const { user_id, type, item_id, title } = data;
|
||||
|
||||
if (!user_id || !type || !item_id || !title) {
|
||||
return res.json({
|
||||
success: false,
|
||||
message: 'Dados de pagamento incompletos'
|
||||
});
|
||||
}
|
||||
|
||||
// Primeiro verifica se o usuário já tem esse item (evita duplicatas)
|
||||
model.checkItem(user_id, item_id, (err, results) => {
|
||||
if (err) {
|
||||
return res.json({
|
||||
success: false,
|
||||
error: err,
|
||||
message: 'Erro ao verificar item existente'
|
||||
});
|
||||
}
|
||||
|
||||
// Se já tem, informa que não precisa adicionar novamente
|
||||
if (results.length > 0) {
|
||||
return res.json({
|
||||
success: false,
|
||||
message: 'Usuário já possui este item em sua biblioteca'
|
||||
});
|
||||
}
|
||||
|
||||
// Se não tem, adiciona o item
|
||||
model.addItem(data, (err) => {
|
||||
if (err) {
|
||||
return res.json({
|
||||
success: false,
|
||||
error: err,
|
||||
message: 'Erro ao adicionar item após pagamento'
|
||||
});
|
||||
}
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: 'Pagamento aprovado! Item adicionado à biblioteca.'
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
const model = require('../models/libraryModel');
|
||||
|
||||
// Este é o "cérebro" do nosso microsserviço!
|
||||
// O controller recebe as requisições HTTP, valida os dados,
|
||||
// chama as funções do model e retorna respostas apropriadas.
|
||||
// É como o gerente que coordena tudo.
|
||||
|
||||
// Função para adicionar um item manualmente à biblioteca.
|
||||
// Pode ser usado para correções ou imports especiais.
|
||||
exports.addItem = (req, res) => {
|
||||
// Usa o user_id do token JWT para segurança (req.auth)
|
||||
const user_id = req.auth?.id;
|
||||
|
||||
// Validação básica dos dados obrigatórios
|
||||
const { type, item_id, title } = req.body;
|
||||
|
||||
if (!user_id || !type || !item_id || !title) {
|
||||
return res.json({
|
||||
success: false,
|
||||
message: 'Dados obrigatórios faltando: user_id, type, item_id, title'
|
||||
});
|
||||
}
|
||||
|
||||
// Só aceitamos tipos válidos para manter consistência
|
||||
if (!['game', 'gift_card'].includes(type)) {
|
||||
return res.json({
|
||||
success: false,
|
||||
message: 'Tipo inválido. Use "game" ou "gift_card"'
|
||||
});
|
||||
}
|
||||
|
||||
// Chama o model para adicionar o item
|
||||
model.addItem({ user_id, type, item_id, title }, (err) => {
|
||||
if (err) {
|
||||
return res.json({
|
||||
success: false,
|
||||
error: err,
|
||||
message: 'Erro ao adicionar item à biblioteca'
|
||||
});
|
||||
}
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: 'Item adicionado à biblioteca com sucesso!'
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// Função que retorna toda a biblioteca de um usuário.
|
||||
// É chamada quando o usuário abre sua página de biblioteca.
|
||||
exports.getLibrary = (req, res) => {
|
||||
// Usa o user_id do token JWT para segurança (req.auth)
|
||||
const user_id = req.auth?.id;
|
||||
|
||||
// Validação do ID do usuário
|
||||
if (!user_id || isNaN(user_id)) {
|
||||
return res.json({
|
||||
success: false,
|
||||
message: 'ID do usuário inválido'
|
||||
});
|
||||
}
|
||||
|
||||
// Busca todos os itens do usuário
|
||||
model.getUserLibrary(user_id, (err, results) => {
|
||||
if (err) {
|
||||
return res.json({
|
||||
success: false,
|
||||
error: err,
|
||||
message: 'Erro ao buscar biblioteca'
|
||||
});
|
||||
}
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: results,
|
||||
message: `Encontrados ${results.length} itens na biblioteca`
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// Esta é a função mais importante para integração!
|
||||
// É chamada AUTOMATICAMENTE pelo serviço de pagamentos quando uma compra é aprovada.
|
||||
// Garante que o usuário receba seu jogo/gift card na biblioteca.
|
||||
exports.paymentApproved = (req, res) => {
|
||||
const data = req.body;
|
||||
|
||||
// Validações rigorosas pois isso vem de outro serviço
|
||||
const { user_id, type, item_id, title } = data;
|
||||
|
||||
if (!user_id || !type || !item_id || !title) {
|
||||
return res.json({
|
||||
success: false,
|
||||
message: 'Dados de pagamento incompletos'
|
||||
});
|
||||
}
|
||||
|
||||
// Primeiro verifica se o usuário já tem esse item (evita duplicatas)
|
||||
model.checkItem(user_id, item_id, (err, results) => {
|
||||
if (err) {
|
||||
return res.json({
|
||||
success: false,
|
||||
error: err,
|
||||
message: 'Erro ao verificar item existente'
|
||||
});
|
||||
}
|
||||
|
||||
// Se já tem, informa que não precisa adicionar novamente
|
||||
if (results.length > 0) {
|
||||
return res.json({
|
||||
success: false,
|
||||
message: 'Usuário já possui este item em sua biblioteca'
|
||||
});
|
||||
}
|
||||
|
||||
// Se não tem, adiciona o item
|
||||
model.addItem(data, (err) => {
|
||||
if (err) {
|
||||
return res.json({
|
||||
success: false,
|
||||
error: err,
|
||||
message: 'Erro ao adicionar item após pagamento'
|
||||
});
|
||||
}
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: 'Pagamento aprovado! Item adicionado à biblioteca.'
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,33 +1,33 @@
|
||||
const db = require('../config/db');
|
||||
|
||||
// Este arquivo é o nosso "guarda-roupa" - aqui guardamos todas as funções
|
||||
// que interagem diretamente com o banco de dados da biblioteca.
|
||||
// Seguimos o padrão MVC: Model lida com dados, Controller com lógica, View com apresentação.
|
||||
|
||||
// Função para adicionar um item (jogo ou gift card) à biblioteca do usuário.
|
||||
// É chamada quando um pagamento é aprovado ou quando queremos adicionar manualmente.
|
||||
exports.addItem = (data, callback) => {
|
||||
// SQL preparado para evitar injeção de código malicioso
|
||||
// Campos: user_id (quem comprou), type (jogo ou gift card), item_id (ID do item),
|
||||
// title (nome do jogo/gift), platform (onde roda ou vale)
|
||||
const sql = `INSERT INTO users_library (user_id, type, item_id, title, platform)
|
||||
VALUES (?, ?, ?, ?, ?)`;
|
||||
|
||||
// Executa a query com os dados sanitizados
|
||||
db.query(sql, [data.user_id, data.type, data.item_id, data.title, data.platform], callback);
|
||||
};
|
||||
|
||||
// Função que busca TODOS os itens da biblioteca de um usuário específico.
|
||||
// É usada quando o usuário quer ver sua coleção completa.
|
||||
exports.getUserLibrary = (user_id, callback) => {
|
||||
// Query simples mas eficiente - busca tudo do usuário
|
||||
db.query('SELECT * FROM users_library WHERE user_id = ?', [user_id], callback);
|
||||
};
|
||||
|
||||
// Função importante para evitar duplicatas!
|
||||
// Antes de adicionar um item, verificamos se o usuário já não o tem.
|
||||
// Isso evita que alguém compre o mesmo jogo duas vezes por acidente.
|
||||
exports.checkItem = (user_id, item_id, callback) => {
|
||||
// Busca se existe algum registro com esse usuário e item
|
||||
db.query('SELECT * FROM users_library WHERE user_id = ? AND item_id = ?', [user_id, item_id], callback);
|
||||
};
|
||||
const db = require('../config/db');
|
||||
|
||||
// Este arquivo é o nosso "guarda-roupa" - aqui guardamos todas as funções
|
||||
// que interagem diretamente com o banco de dados da biblioteca.
|
||||
// Seguimos o padrão MVC: Model lida com dados, Controller com lógica, View com apresentação.
|
||||
|
||||
// Função para adicionar um item (jogo ou gift card) à biblioteca do usuário.
|
||||
// É chamada quando um pagamento é aprovado ou quando queremos adicionar manualmente.
|
||||
exports.addItem = (data, callback) => {
|
||||
// SQL preparado para evitar injeção de código malicioso
|
||||
// Campos: user_id (quem comprou), type (jogo ou gift card), item_id (ID do item),
|
||||
// title (nome do jogo/gift), platform (onde roda ou vale)
|
||||
const sql = `INSERT INTO users_library (user_id, type, item_id, title, platform)
|
||||
VALUES (?, ?, ?, ?, ?)`;
|
||||
|
||||
// Executa a query com os dados sanitizados
|
||||
db.query(sql, [data.user_id, data.type, data.item_id, data.title, data.platform], callback);
|
||||
};
|
||||
|
||||
// Função que busca TODOS os itens da biblioteca de um usuário específico.
|
||||
// É usada quando o usuário quer ver sua coleção completa.
|
||||
exports.getUserLibrary = (user_id, callback) => {
|
||||
// Query simples mas eficiente - busca tudo do usuário
|
||||
db.query('SELECT * FROM users_library WHERE user_id = ?', [user_id], callback);
|
||||
};
|
||||
|
||||
// Função importante para evitar duplicatas!
|
||||
// Antes de adicionar um item, verificamos se o usuário já não o tem.
|
||||
// Isso evita que alguém compre o mesmo jogo duas vezes por acidente.
|
||||
exports.checkItem = (user_id, item_id, callback) => {
|
||||
// Busca se existe algum registro com esse usuário e item
|
||||
db.query('SELECT * FROM users_library WHERE user_id = ? AND item_id = ?', [user_id, item_id], callback);
|
||||
};
|
||||
|
||||
@@ -1,26 +1,27 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const controller = require('../controllers/libraryController');
|
||||
|
||||
// Este arquivo define as "portas de entrada" da nossa API!
|
||||
// Cada rota é como uma porta específica do prédio - cada uma leva a um lugar diferente.
|
||||
// Seguimos convenções REST: POST para criar, GET para buscar.
|
||||
|
||||
// Rota para adicionar um item manualmente à biblioteca
|
||||
// Método: POST /library/add
|
||||
// Uso: Para correções ou imports especiais (não para compras normais)
|
||||
router.post('/add', controller.addItem);
|
||||
|
||||
// Rota para buscar toda a biblioteca de um usuário
|
||||
// Método: GET /library/user/:user_id
|
||||
// Exemplo: GET /library/user/123 retorna todos os jogos e gift cards do usuário 123
|
||||
router.get('/user/:user_id', controller.getLibrary);
|
||||
|
||||
// Rota CRUCIAL para integração com o serviço de pagamentos!
|
||||
// Método: POST /library/integration/payment-approved
|
||||
// Esta rota é chamada AUTOMATICAMENTE quando um pagamento é aprovado.
|
||||
// É o elo entre "comprou" e "recebeu na biblioteca".
|
||||
router.post('/integration/payment-approved', controller.paymentApproved);
|
||||
|
||||
// Exportamos o router para que o app.js possa usar essas rotas
|
||||
module.exports = router;
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const controller = require('../controllers/libraryController');
|
||||
const { authenticateToken } = require('../config/authMiddleware');
|
||||
|
||||
// Este arquivo define as "portas de entrada" da nossa API!
|
||||
// Cada rota é como uma porta específica do prédio - cada uma leva a um lugar diferente.
|
||||
// Seguimos convenções REST: POST para criar, GET para buscar.
|
||||
|
||||
// Rota para adicionar um item manualmente à biblioteca
|
||||
// Método: POST /library/add
|
||||
// Uso: Para correções ou imports especiais (não para compras normais)
|
||||
router.post('/add', authenticateToken, controller.addItem);
|
||||
|
||||
// Rota para buscar toda a biblioteca de um usuário
|
||||
// Método: GET /library/user/:user_id
|
||||
// Exemplo: GET /library/user/123 retorna todos os jogos e gift cards do usuário 123
|
||||
router.get('/user/:user_id', authenticateToken, controller.getLibrary);
|
||||
|
||||
// Rota CRUCIAL para integração com o serviço de pagamentos!
|
||||
// Método: POST /library/integration/payment-approved
|
||||
// Esta rota é chamada AUTOMATICAMENTE quando um pagamento é aprovado.
|
||||
// É o elo entre "comprou" e "recebeu na biblioteca".
|
||||
router.post('/integration/payment-approved', controller.paymentApproved);
|
||||
|
||||
// Exportamos o router para que o app.js possa usar essas rotas
|
||||
module.exports = router;
|
||||
|
||||
Reference in New Issue
Block a user