Skip to main content
Glama

MCP PostgreSQL Server

by Maxim2324
security.js4.06 kB
const { ValidationError } = require('./error-handler'); const config = require('../config/config'); class SecurityMiddleware { static validateApiKey(req, res, next) { const apiKey = req.headers['x-api-key']; if (!apiKey) { throw new ValidationError('API key is required'); } if (apiKey !== config.apiKey) { throw new ValidationError('Invalid API key'); } next(); } static checkPermissions(req, res, next) { const userRole = req.headers['x-user-role']; if (!userRole) { throw new ValidationError('User role is required'); } const allowedRoles = ['admin', 'user', 'readonly']; if (!allowedRoles.includes(userRole)) { throw new ValidationError('Invalid user role'); } // Check if user has permission for the requested operation const operation = req.method + ' ' + req.path; const permissions = { admin: ['*'], user: ['GET *', 'POST /api/query', 'POST /api/query/explain'], readonly: ['GET *'] }; const hasPermission = permissions[userRole].some(pattern => { if (pattern === '*') return true; if (pattern.endsWith('*')) { return operation.startsWith(pattern.slice(0, -1)); } return operation === pattern; }); if (!hasPermission) { throw new ValidationError('Permission denied'); } next(); } static sanitizeInput(req, res, next) { // Sanitize query parameters if (req.query) { Object.keys(req.query).forEach(key => { if (typeof req.query[key] === 'string') { req.query[key] = this.sanitizeString(req.query[key]); } }); } // Sanitize body parameters if (req.body) { Object.keys(req.body).forEach(key => { if (typeof req.body[key] === 'string') { req.body[key] = this.sanitizeString(req.body[key]); } }); } // Sanitize URL parameters if (req.params) { Object.keys(req.params).forEach(key => { if (typeof req.params[key] === 'string') { req.params[key] = this.sanitizeString(req.params[key]); } }); } next(); } static sanitizeString(str) { // Remove potentially dangerous characters return str.replace(/[<>'"]/g, ''); } static validateContentType(req, res, next) { const contentType = req.headers['content-type']; if (req.method === 'POST' || req.method === 'PUT') { if (!contentType || !contentType.includes('application/json')) { throw new ValidationError('Content-Type must be application/json'); } } next(); } static rateLimit(req, res, next) { const clientIp = req.ip; const now = Date.now(); // Initialize rate limit tracking if not exists if (!this.rateLimits) { this.rateLimits = new Map(); } // Get or create rate limit info for this IP let limitInfo = this.rateLimits.get(clientIp); if (!limitInfo) { limitInfo = { count: 0, resetTime: now + config.rateLimit.window }; this.rateLimits.set(clientIp, limitInfo); } // Check if window has expired if (now > limitInfo.resetTime) { limitInfo.count = 0; limitInfo.resetTime = now + config.rateLimit.window; } // Check if limit exceeded if (limitInfo.count >= config.rateLimit.max) { throw new ValidationError('Rate limit exceeded'); } // Increment count limitInfo.count++; next(); } } module.exports = SecurityMiddleware;

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Maxim2324/mcp-server-test'

If you have feedback or need assistance with the MCP directory API, please join our Discord server