Initial LinkedSign platform

This commit is contained in:
2026-04-06 20:33:59 -05:00
commit 1074c7c9d2
159 changed files with 19072 additions and 0 deletions
@@ -0,0 +1,15 @@
const rateLimit = require('express-rate-limit');
const authRateLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 20,
standardHeaders: true,
legacyHeaders: false,
message: {
success: false,
data: null,
error: 'Too many login attempts. Please try again later.',
},
});
module.exports = authRateLimiter;
+19
View File
@@ -0,0 +1,19 @@
const { verify } = require('../utils/jwt');
const authenticate = (req, res, next) => {
const authHeader = req.headers['authorization'];
if (!authHeader || !authHeader.startsWith('Bearer ')) {
return res.status(401).json({ success: false, data: null, error: 'Authorization token required.' });
}
const token = authHeader.slice(7);
try {
const decoded = verify(token);
req.user = { id: decoded.sub, email: decoded.email, role: decoded.role, name: decoded.name };
return next();
} catch {
return res.status(401).json({ success: false, data: null, error: 'Invalid or expired token.' });
}
};
module.exports = authenticate;
+29
View File
@@ -0,0 +1,29 @@
const { sendError } = require('../utils/apiResponse');
const errorHandler = (err, req, res, next) => {
if (res.headersSent) {
return next(err);
}
const statusCode = err.statusCode || 500;
if (statusCode >= 500) {
console.error(`[ERROR ${statusCode}]`, err.message);
console.error(err.stack?.split('\n').slice(0, 6).join('\n'));
}
const message = err.code
? (err.message || 'Request error')
: (statusCode >= 500 ? 'Internal server error' : err.message || 'Request error');
if (err.code) {
return res.status(statusCode).json({
success: false,
data: err.data || null,
error: message,
code: err.code,
});
}
return sendError(res, message, statusCode);
};
module.exports = errorHandler;
+28
View File
@@ -0,0 +1,28 @@
const path = require('path');
const MAX_FILE_SIZE = 10 * 1024 * 1024;
const fileValidator = (req, res, next) => {
const file = req.file;
if (!file) {
const error = new Error('Invalid file upload');
error.statusCode = 400;
return next(error);
}
const extension = path.extname(file.originalname || '').toLowerCase();
const isPdfMimeType = file.mimetype === 'application/pdf';
const isPdfExtension = extension === '.pdf';
const isValidSize = typeof file.size === 'number' && file.size <= MAX_FILE_SIZE;
if (!isPdfMimeType || !isPdfExtension || !isValidSize) {
const error = new Error('Invalid file upload');
error.statusCode = 400;
return next(error);
}
return next();
};
module.exports = fileValidator;
+7
View File
@@ -0,0 +1,7 @@
const { sendError } = require('../utils/apiResponse');
const notFound = (req, res) => {
return sendError(res, `Route not found: ${req.method} ${req.originalUrl}`, 404);
};
module.exports = notFound;