Add delete-all-data endpoint to auth API for user data removal
Despliegue Automático / desplegar (push) Successful in 1m7s

This commit is contained in:
2026-05-20 17:25:46 +02:00
parent a44f7a8253
commit 87cde27436
4 changed files with 72 additions and 2 deletions
+16
View File
@@ -147,6 +147,22 @@ Respuesta ejemplo:
}
```
### `POST /api/auth/delete-all-data`
Elimina todas las notas, categorías y refresh tokens del usuario autenticado. El usuario se conserva.
Headers:
- `Authorization: Bearer <accessToken>`: obligatorio.
Respuesta ejemplo:
```json
{
"message": "Datos del usuario eliminados correctamente; se eliminaron todos los tokens."
}
```
### `POST /api/sync`
Endpoint único de sincronización offline-first.
+34 -2
View File
@@ -1,4 +1,11 @@
const authService = require('../services/authService');
const jwt = require('jsonwebtoken');
const JWT_SECRET = process.env.JWT_SECRET;
if (!JWT_SECRET) {
throw new Error('JWT_SECRET no está definido');
}
// 1. REGISTRO
const register = async (req, res) => {
@@ -73,5 +80,30 @@ const logout = async (req, res) => {
}
};
// ¡EXPORTAMOS LAS 4 FUNCIONES!
module.exports = { register, login, refresh, logout };
const deleteAllData = async (req, res) => {
try {
const authorizationHeader = req.headers.authorization || '';
if (!authorizationHeader.startsWith('Bearer ')) {
return res.status(401).json({ error: 'Authorization header missing or invalid' });
}
const token = authorizationHeader.slice(7).trim();
const payload = jwt.verify(token, JWT_SECRET);
const userId = payload && payload.id;
if (!userId) return res.status(401).json({ error: 'Usuario inválido en token' });
const result = await authService.deleteAllUserData(userId);
res.json(result);
} catch (error) {
if (error.name === 'JsonWebTokenError' || error.name === 'TokenExpiredError') {
return res.status(401).json({ error: 'Token inválido o expirado' });
}
const statusCode = error.message.includes('obligatorio') || error.message.includes('inválido') ? 400 : 500;
res.status(statusCode).json({ error: error.message });
}
};
// Exportamos los handlers de auth.
module.exports = { register, login, refresh, logout, deleteAllData };
+3
View File
@@ -14,4 +14,7 @@ router.post('/refresh', authController.refresh);
// POST /api/auth/logout
router.post('/logout', authController.logout);
// POST /api/auth/delete-all-data
router.post('/delete-all-data', authController.deleteAllData);
module.exports = router;
+19
View File
@@ -1,7 +1,10 @@
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const crypto = require('crypto');
const sequelize = require('../config/database');
const User = require('../models/User');
const Note = require('../models/Note');
const Category = require('../models/Category');
const RefreshToken = require('../models/RefreshToken');
const JWT_SECRET = process.env.JWT_SECRET;
@@ -85,6 +88,22 @@ class AuthService {
await RefreshToken.destroy({ where: { userId } });
return { message: 'Se ha cerrado sesión en todos los dispositivos de forma global.' };
}
async deleteAllUserData(userId) {
if (!userId) {
throw new Error('userId es obligatorio');
}
return sequelize.transaction(async (transaction) => {
await Note.destroy({ where: { userId }, transaction });
await Category.destroy({ where: { userId }, transaction });
await RefreshToken.destroy({ where: { userId }, transaction });
return {
message: 'Datos del usuario eliminados correctamente; se eliminaron todos los tokens.'
};
});
}
}
module.exports = new AuthService();