Harden dev environment configuration
This commit is contained in:
		
							
								
								
									
										27
									
								
								backend/src/config/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								backend/src/config/index.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| const dotenv = require('dotenv'); | ||||
|  | ||||
| dotenv.config(); | ||||
|  | ||||
| const optionalNumber = (value, fallback) => { | ||||
|   const parsed = parseInt(value, 10); | ||||
|   return Number.isFinite(parsed) ? parsed : fallback; | ||||
| }; | ||||
|  | ||||
| const config = { | ||||
|   env: process.env.NODE_ENV || 'development', | ||||
|   host: process.env.HOST || process.env.BACKEND_HOST || '0.0.0.0', | ||||
|   port: optionalNumber(process.env.PORT || process.env.BACKEND_PORT, 3001), | ||||
|   databaseUrl: process.env.DATABASE_URL, | ||||
|   jwtSecret: process.env.JWT_SECRET, | ||||
|   corsOrigin: process.env.CORS_ORIGIN || '*', | ||||
|   logLevel: process.env.LOG_LEVEL || 'info' | ||||
| }; | ||||
|  | ||||
| const required = ['databaseUrl', 'jwtSecret']; | ||||
| const missingKeys = required.filter((key) => !config[key]); | ||||
|  | ||||
| if (missingKeys.length > 0) { | ||||
|   throw new Error(`Missing required environment variables: ${missingKeys.join(', ')}`); | ||||
| } | ||||
|  | ||||
| module.exports = config; | ||||
| @@ -1,14 +1,16 @@ | ||||
| const { Pool } = require('pg'); | ||||
| require('dotenv').config(); | ||||
| const config = require('../config'); | ||||
|  | ||||
| const pool = new Pool({ | ||||
|   connectionString: process.env.DATABASE_URL, | ||||
|   ssl: process.env.NODE_ENV === 'production' ? { rejectUnauthorized: false } : false | ||||
|   connectionString: config.databaseUrl, | ||||
|   ssl: config.env === 'production' ? { rejectUnauthorized: false } : false | ||||
| }); | ||||
|  | ||||
| // Test database connection | ||||
| pool.on('connect', () => { | ||||
|   console.log('Connected to MerchantsOfHope-SupplyANdDemandPortal database'); | ||||
|   if (config.logLevel !== 'silent') { | ||||
|     console.log('Connected to MerchantsOfHope-SupplyANdDemandPortal database'); | ||||
|   } | ||||
| }); | ||||
|  | ||||
| pool.on('error', (err) => { | ||||
|   | ||||
							
								
								
									
										6
									
								
								backend/src/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								backend/src/index.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| const app = require('./server'); | ||||
| const config = require('./config'); | ||||
|  | ||||
| app.listen(config.port, config.host, () => { | ||||
|   console.log(`MerchantsOfHope-SupplyANdDemandPortal backend server running on ${config.host}:${config.port}`); | ||||
| }); | ||||
| @@ -1,5 +1,6 @@ | ||||
| const jwt = require('jsonwebtoken'); | ||||
| const pool = require('../database/connection'); | ||||
| const config = require('../config'); | ||||
|  | ||||
| const authenticateToken = async (req, res, next) => { | ||||
|   const authHeader = req.headers['authorization']; | ||||
| @@ -10,7 +11,7 @@ const authenticateToken = async (req, res, next) => { | ||||
|   } | ||||
|  | ||||
|   try { | ||||
|     const decoded = jwt.verify(token, process.env.JWT_SECRET); | ||||
|     const decoded = jwt.verify(token, config.jwtSecret); | ||||
|      | ||||
|     // Get user details from database | ||||
|     const userResult = await pool.query( | ||||
|   | ||||
| @@ -4,6 +4,7 @@ const jwt = require('jsonwebtoken'); | ||||
| const { body, validationResult } = require('express-validator'); | ||||
| const pool = require('../database/connection'); | ||||
| const { authenticateToken } = require('../middleware/auth'); | ||||
| const config = require('../config'); | ||||
|  | ||||
| const router = express.Router(); | ||||
|  | ||||
| @@ -47,7 +48,7 @@ router.post('/register', [ | ||||
|     // Generate JWT token | ||||
|     const token = jwt.sign( | ||||
|       { userId: user.id, email: user.email, role: user.role }, | ||||
|       process.env.JWT_SECRET, | ||||
|       config.jwtSecret, | ||||
|       { expiresIn: '24h' } | ||||
|     ); | ||||
|  | ||||
| @@ -106,7 +107,7 @@ router.post('/login', [ | ||||
|     // Generate JWT token | ||||
|     const token = jwt.sign( | ||||
|       { userId: user.id, email: user.email, role: user.role }, | ||||
|       process.env.JWT_SECRET, | ||||
|       config.jwtSecret, | ||||
|       { expiresIn: '24h' } | ||||
|     ); | ||||
|  | ||||
|   | ||||
| @@ -2,7 +2,7 @@ const express = require('express'); | ||||
| const cors = require('cors'); | ||||
| const helmet = require('helmet'); | ||||
| const morgan = require('morgan'); | ||||
| require('dotenv').config(); | ||||
| const config = require('./config'); | ||||
|  | ||||
| const authRoutes = require('./routes/auth'); | ||||
| const userRoutes = require('./routes/users'); | ||||
| @@ -13,16 +13,19 @@ const applicationRoutes = require('./routes/applications'); | ||||
| const resumeRoutes = require('./routes/resumes'); | ||||
|  | ||||
| const app = express(); | ||||
| const PORT = process.env.PORT || 3001; | ||||
|  | ||||
| // Middleware | ||||
| app.disable('x-powered-by'); | ||||
|  | ||||
| const corsOrigins = config.corsOrigin === '*' | ||||
|   ? undefined | ||||
|   : config.corsOrigin.split(',').map((origin) => origin.trim()); | ||||
|  | ||||
| app.use(helmet()); | ||||
| app.use(cors()); | ||||
| app.use(morgan('combined')); | ||||
| app.use(cors(corsOrigins ? { origin: corsOrigins, credentials: true } : {})); | ||||
| app.use(morgan(config.env === 'production' ? 'combined' : 'dev')); | ||||
| app.use(express.json({ limit: '10mb' })); | ||||
| app.use(express.urlencoded({ extended: true })); | ||||
|  | ||||
| // Routes | ||||
| app.use('/api/auth', authRoutes); | ||||
| app.use('/api/users', userRoutes); | ||||
| app.use('/api/employers', employerRoutes); | ||||
| @@ -31,27 +34,21 @@ app.use('/api/jobs', jobRoutes); | ||||
| app.use('/api/applications', applicationRoutes); | ||||
| app.use('/api/resumes', resumeRoutes); | ||||
|  | ||||
| // Health check | ||||
| app.get('/api/health', (req, res) => { | ||||
|   res.json({ status: 'OK', timestamp: new Date().toISOString() }); | ||||
| }); | ||||
|  | ||||
| // Error handling middleware | ||||
| // eslint-disable-next-line no-unused-vars | ||||
| app.use((err, req, res, next) => { | ||||
|   console.error(err.stack); | ||||
|   res.status(500).json({  | ||||
|   res.status(500).json({ | ||||
|     error: 'Something went wrong!', | ||||
|     message: process.env.NODE_ENV === 'development' ? err.message : 'Internal server error' | ||||
|     message: config.env === 'development' ? err.message : 'Internal server error' | ||||
|   }); | ||||
| }); | ||||
|  | ||||
| // 404 handler | ||||
| app.use('*', (req, res) => { | ||||
|   res.status(404).json({ error: 'Route not found' }); | ||||
| }); | ||||
|  | ||||
| app.listen(PORT, () => { | ||||
|   console.log(`MerchantsOfHope-SupplyANdDemandPortal backend server running on port ${PORT}`); | ||||
| }); | ||||
|  | ||||
| module.exports = app; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user