-
Notifications
You must be signed in to change notification settings - Fork 591
Frontend1 #21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Frontend1 #21
Changes from all commits
d6d24c5
eeae9b5
0fd3ce9
0cc3f18
39679d1
41463cd
9f3344c
efde903
0a107f6
2313dbe
95b04f1
7a4b43c
22e5994
7a40372
215dee2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
MONGO_URI=mongodb://localhost:27017/digital-mess-card | ||
JWT_SECRET=your-secret-key | ||
PORT=5000 | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
# Logs | ||
logs | ||
*.log | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
lerna-debug.log* | ||
.pnpm-debug.log* | ||
|
||
# Diagnostic reports (https://nodejs.org/api/report.html) | ||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json | ||
|
||
# Runtime data | ||
pids | ||
*.pid | ||
*.seed | ||
*.pid.lock | ||
|
||
# Directory for instrumented libs generated by jscoverage/JSCover | ||
lib-cov | ||
|
||
# Coverage directory used by tools like istanbul | ||
coverage | ||
*.lcov | ||
|
||
# nyc test coverage | ||
.nyc_output | ||
|
||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) | ||
.grunt | ||
|
||
# Bower dependency directory (https://bower.io/) | ||
bower_components | ||
|
||
# node-waf configuration | ||
.lock-wscript | ||
|
||
# Compiled binary addons (https://nodejs.org/api/addons.html) | ||
build/Release | ||
|
||
# Dependency directories | ||
node_modules/ | ||
jspm_packages/ | ||
|
||
# Snowpack dependency directory (https://snowpack.dev/) | ||
web_modules/ | ||
|
||
# TypeScript cache | ||
*.tsbuildinfo | ||
|
||
# Optional npm cache directory | ||
.npm | ||
|
||
# Optional eslint cache | ||
.eslintcache | ||
|
||
# Optional stylelint cache | ||
.stylelintcache | ||
|
||
# Microbundle cache | ||
.rpt2_cache/ | ||
.rts2_cache_cjs/ | ||
.rts2_cache_es/ | ||
.rts2_cache_umd/ | ||
|
||
# Optional REPL history | ||
.node_repl_history | ||
|
||
# Output of 'npm pack' | ||
*.tgz | ||
|
||
# Yarn Integrity file | ||
.yarn-integrity | ||
|
||
# dotenv environment variable files | ||
.env | ||
.env.development.local | ||
.env.test.local | ||
.env.production.local | ||
.env.local | ||
|
||
# parcel-bundler cache (https://parceljs.org/) | ||
.cache | ||
.parcel-cache | ||
|
||
# Next.js build output | ||
.next | ||
out | ||
|
||
# Nuxt.js build / generate output | ||
.nuxt | ||
dist | ||
|
||
# Gatsby files | ||
.cache/ | ||
# Comment in the public line in if your project uses Gatsby and not Next.js | ||
# https://nextjs.org/blog/next-9-1#public-directory-support | ||
# public | ||
|
||
# vuepress build output | ||
.vuepress/dist | ||
|
||
# vuepress v2.x temp and cache directory | ||
.temp | ||
.cache | ||
|
||
# vitepress build output | ||
**/.vitepress/dist | ||
|
||
# vitepress cache directory | ||
**/.vitepress/cache | ||
|
||
# Docusaurus cache and generated files | ||
.docusaurus | ||
|
||
# Serverless directories | ||
.serverless/ | ||
|
||
# FuseBox cache | ||
.fusebox/ | ||
|
||
# DynamoDB Local files | ||
.dynamodb/ | ||
|
||
# TernJS port file | ||
.tern-port | ||
|
||
# Stores VSCode versions used for testing VSCode extensions | ||
.vscode-test | ||
|
||
# yarn v2 | ||
.yarn/cache | ||
.yarn/unplugged | ||
.yarn/build-state.yml | ||
.yarn/install-state.gz | ||
.pnp.* |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,27 @@ | ||||||||||||||||||||||||||||||||||||
require('dotenv').config(); | ||||||||||||||||||||||||||||||||||||
const express= require('express'); | ||||||||||||||||||||||||||||||||||||
const app = express(); | ||||||||||||||||||||||||||||||||||||
const cors = require('cors'); | ||||||||||||||||||||||||||||||||||||
const connectDB = require('./config/db'); | ||||||||||||||||||||||||||||||||||||
Comment on lines
+1
to
+5
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Configure CORS with specific options for security. The current CORS setup allows requests from any origin. For security, configure CORS with specific options. Apply this diff: -const express= require('express');
+const express = require('express');
const app = express();
const cors = require('cors');
+const corsOptions = {
+ origin: process.env.ALLOWED_ORIGINS?.split(',') || 'http://localhost:3000',
+ methods: ['GET', 'POST'],
+ credentials: true,
+ optionsSuccessStatus: 204
+}; 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
const authRoutes = require('./routes/auth'); | ||||||||||||||||||||||||||||||||||||
const scanRoutes= require('./routes/scan'); | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
app.use(cors()); | ||||||||||||||||||||||||||||||||||||
app.use(express.json()); | ||||||||||||||||||||||||||||||||||||
Comment on lines
+10
to
+11
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add essential security middleware. Add security middleware and update CORS configuration. Apply this diff: -app.use(cors());
+app.use(cors(corsOptions));
app.use(express.json());
+app.use(express.urlencoded({ extended: true }));
+app.use(require('helmet')());
+app.use(require('express-rate-limit')({
+ windowMs: 15 * 60 * 1000, // 15 minutes
+ max: 100 // limit each IP to 100 requests per windowMs
+})); Don't forget to install the required packages: npm install helmet express-rate-limit |
||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
connectDB(); | ||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add error handling for database connection. The database connection should be handled with proper error management. Apply this diff: -connectDB();
+connectDB().catch(err => {
+ console.error('Failed to connect to database:', err);
+ process.exit(1);
+}); 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
app.use('/api/auth', authRoutes); | ||||||||||||||||||||||||||||||||||||
app.use('/api/scan', scanRoutes); | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
app.get('/',(req,res)=>{ | ||||||||||||||||||||||||||||||||||||
res.send('Digital MESS Card'); //Route | ||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
const PORT= process.env.PORT || 5000; | ||||||||||||||||||||||||||||||||||||
app.listen(PORT, () => { | ||||||||||||||||||||||||||||||||||||
console.log(`Server running on http://localhost:${PORT}`); | ||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||
Comment on lines
+24
to
+27
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add graceful shutdown handling and improve logging. Implement proper server shutdown handling and enhance logging. Apply this diff: const PORT = process.env.PORT || 5000;
-app.listen(PORT, () => {
- console.log(`Server running on http://localhost:${PORT}`);
+const server = app.listen(PORT, () => {
+ console.log(`Server running on http://localhost:${PORT}`);
+});
+
+// Graceful shutdown handling
+process.on('SIGTERM', () => {
+ console.log('SIGTERM signal received: closing HTTP server');
+ server.close(() => {
+ console.log('HTTP server closed');
+ process.exit(0);
+ });
}); 📝 Committable suggestion
Suggested change
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
const mongoose= require('mongoose'); | ||
|
||
const connectDB = async () => { | ||
try { | ||
await mongoose.connect(process.env.MONGO_URI); | ||
console.log('MongoDB connected'); | ||
} catch (err) { | ||
console.error('MongoDB connection error:', err); | ||
process.exit(1); | ||
} | ||
}; | ||
|
||
module.exports = connectDB; |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,30 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const bcrypt = require('bcryptjs'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const jwt = require('jsonwebtoken'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const User = require('../models/User'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const jwtSecret = process.env.JWT_SECRET; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
exports.register = async (req, res) => { //to register new user | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const { username, password } = req.body; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const hashedPassword = await bcrypt.hash(password, 10); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const user = new User({ username, password: hashedPassword }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
await user.save(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
res.status(201).json({ message: 'User registered successfully' }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} catch (err) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
res.status(500).json({ error: 'Error registering user' }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+6
to
+16
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add input validation and security measures to registration. The registration endpoint needs several security improvements:
+const { body, validationResult } = require('express-validator');
+const rateLimit = require('express-rate-limit');
+
+const registerLimiter = rateLimit({
+ windowMs: 60 * 60 * 1000, // 1 hour
+ max: 5 // limit each IP to 5 registration requests per hour
+});
+
-exports.register = async (req, res) => {
+exports.register = [
+ registerLimiter,
+ body('username').trim().isLength({ min: 3 }).escape(),
+ body('password')
+ .isLength({ min: 8 })
+ .matches(/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z0-9]).{8,}$/),
+ async (req, res) => {
const { username, password } = req.body;
+
+ const errors = validationResult(req);
+ if (!errors.isEmpty()) {
+ return res.status(400).json({ errors: errors.array() });
+ }
+
try {
const hashedPassword = await bcrypt.hash(password, 10);
const user = new User({ username, password: hashedPassword });
await user.save();
res.status(201).json({ message: 'User registered successfully' });
} catch (err) {
- res.status(500).json({ error: 'Error registering user' });
+ if (err.code === 11000) {
+ return res.status(400).json({ error: 'Username already exists' });
+ }
+ console.error('Registration error:', err);
+ res.status(500).json({ error: 'Internal server error' });
}
-};
+}]; 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
exports.login = async (req, res) => { //Authenticate access | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const { username, password } = req.body; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const user= await User.findOne({ username }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (!user || !(await bcrypt.compare(password, user.password))) { // //to check whether the login details are valid | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return res.status(400).json({ error: 'Invalid credentials' }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const token= jwt.sign({ userId: user._id }, jwtSecret, { expiresIn: '1h' }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
res.json({ token }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} catch (err) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
res.status(500).json({ error: 'Error logging in' }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+18
to
+30
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Enhance login security with rate limiting and secure error handling. The login endpoint needs similar security improvements:
+const loginLimiter = rateLimit({
+ windowMs: 15 * 60 * 1000, // 15 minutes
+ max: 5 // limit each IP to 5 login attempts per 15 minutes
+});
+
-exports.login = async (req, res) => {
+exports.login = [
+ loginLimiter,
+ body('username').trim().escape(),
+ body('password').trim(),
+ async (req, res) => {
const { username, password } = req.body;
+
+ const errors = validationResult(req);
+ if (!errors.isEmpty()) {
+ return res.status(400).json({ errors: errors.array() });
+ }
+
try {
const user= await User.findOne({ username });
- if (!user || !(await bcrypt.compare(password, user.password))) {
+ // Use constant-time comparison to prevent timing attacks
+ const isValid = user ? await bcrypt.compare(password, user.password) : false;
+ if (!isValid) {
return res.status(400).json({ error: 'Invalid credentials' });
}
const token= jwt.sign({ userId: user._id }, jwtSecret, { expiresIn: '1h' });
res.json({ token });
} catch (err) {
- res.status(500).json({ error: 'Error logging in' });
+ console.error('Login error:', err);
+ res.status(500).json({ error: 'Internal server error' });
}
-};
+}]; 📝 Committable suggestion
Suggested change
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
const Scan= require('../models/Scan'); | ||
|
||
exports.scan= async (req, res) => { //to get info about user and the current time | ||
const { type } = req.body; | ||
const userId = req.userId; | ||
Comment on lines
+4
to
+5
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add input validation and improve error handling. The current implementation lacks input validation and uses generic error handling:
Apply this diff to add input validation and improve error handling: const { type } = req.body;
const userId = req.userId;
+ if (!type) {
+ return res.status(400).json({ error: 'Scan type is required' });
+ }
+
+ if (!['lunch', 'snack'].includes(type)) {
+ return res.status(400).json({ error: 'Invalid scan type' });
+ }
try {
const existingScan = await Scan.findOne({ userId, type, date: { $gte: new Date().setHours(0, 0, 0, 0) } });
if (existingScan) {
return res.status(400).json({ error: 'Already scanned today' });
}
const scan = new Scan({ userId, type });
await scan.save();
res.json({ message: 'Scan successful' });
} catch (err) {
- res.status(500).json({ error: 'Error processing scan' });
+ console.error('Scan error:', err);
+ res.status(500).json({
+ error: 'Error processing scan',
+ details: process.env.NODE_ENV === 'development' ? err.message : undefined
+ });
} Also applies to: 19-30 |
||
|
||
const now = new Date(); | ||
const hours = now.getHours(); | ||
const minutes = now.getMinutes(); | ||
|
||
if (type === 'lunch' && !(hours >= 11 && minutes >= 30 && hours < 14)) { //to check whether scanning of lunch time is valid | ||
return res.status(400).json({ error: 'Lunch scanning is only allowed between 11:30 AM and 2:00 PM' }); | ||
} | ||
Comment on lines
+11
to
+13
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix time window validation logic. The current time window checks have logical errors that could allow scans outside the intended windows:
Apply this diff to fix the time window validation: - if (type === 'lunch' && !(hours >= 11 && minutes >= 30 && hours < 14)) {
+ if (type === 'lunch' && (hours < 11 || (hours === 11 && minutes < 30) || hours >= 14)) {
return res.status(400).json({ error: 'Lunch scanning is only allowed between 11:30 AM and 2:00 PM' });
}
- if (type === 'snack' && !(hours >= 15 && minutes >= 30 && hours < 17)) {
+ if (type === 'snack' && (hours < 15 || (hours === 15 && minutes < 30) || hours >= 17)) {
return res.status(400).json({ error: 'Snack scanning is only allowed between 3:30 PM and 5:00 PM' });
} Also applies to: 15-17 |
||
|
||
if (type === 'snack' && !(hours >= 15 && minutes >= 30 && hours < 17)) { //to check whether scanning of snack time is valid | ||
return res.status(400).json({ error: 'Snack scanning is only allowed between 3:30 PM and 5:00 PM' }); | ||
} | ||
|
||
try { | ||
const existingScan = await Scan.findOne({ userId, type, date: { $gte: new Date().setHours(0, 0, 0, 0) } }); | ||
if (existingScan) { | ||
return res.status(400).json({ error: 'Already scanned today' }); //to check whether a scanning already occured in the given time | ||
} | ||
|
||
const scan = new Scan({ userId, type }); | ||
await scan.save(); //to save current scan | ||
res.json({ message: 'Scan successful' }); | ||
} catch (err) { | ||
res.status(500).json({ error: 'Error processing scan' }); | ||
} | ||
}; |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,15 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const jwt= require('jsonwebtoken'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const jwtSecret = process.env.JWT_SECRET; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
exports.authenticate= (req,res,next) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const token=req.header('Authorization'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (!token) return res.status(401).json({ error: 'Access denied' }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
try{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const decoded= jwt.verify(token, jwtSecret); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
req.userId= decoded.userId; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
next(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} catch (err) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
res.status(400).json({ error: 'Invalid token' }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+4
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Enhance JWT authentication security. Several security improvements are recommended:
-exports.authenticate= (req,res,next) => {
- const token=req.header('Authorization');
- if (!token) return res.status(401).json({ error: 'Access denied' });
+exports.authenticate = (req, res, next) => {
+ const authHeader = req.header('Authorization');
+ if (!authHeader) {
+ return res.status(401).json({ error: 'No authorization header' });
+ }
+
+ if (!authHeader.startsWith('Bearer ')) {
+ return res.status(401).json({ error: 'Invalid authorization scheme' });
+ }
+
+ const token = authHeader.split(' ')[1];
try{
- const decoded= jwt.verify(token, jwtSecret);
- req.userId= decoded.userId;
+ const decoded = jwt.verify(token, jwtSecret);
+
+ // Check token expiration
+ if (decoded.exp < Date.now() / 1000) {
+ return res.status(401).json({ error: 'Token has expired' });
+ }
+
+ req.userId = decoded.userId;
next();
} catch (err) {
- res.status(400).json({ error: 'Invalid token' });
+ if (err.name === 'JsonWebTokenError') {
+ return res.status(401).json({ error: 'Invalid token signature' });
+ }
+ res.status(500).json({ error: 'Internal server error' });
}
}; 📝 Committable suggestion
Suggested change
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
const mongoose= require('mongoose'); | ||
const scanSchema =new mongoose.Schema({ //Scan date update in db | ||
userId: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true }, | ||
type: { type: String, enum: ['lunch', 'snack'], required: true }, | ||
date :{ type: Date, default: Date.now}, | ||
}); | ||
|
||
module.exports= mongoose.model('Scan', scanSchema); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
const mongoose= require('mongoose'); | ||
|
||
const userSchema= new mongoose.Schema({ //login details connected to db | ||
username:{ type: String, required: true, unique: true }, | ||
password:{ type: String, required: true, match:/^[a-zA-Z0-9]+$/, | ||
} | ||
}); | ||
module.exports= mongoose.model('User', userSchema); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Security: Update configuration and follow environment file best practices.
The JWT secret is using a weak placeholder value
MongoDB connection lacks authentication
Environment files should not be committed to version control
Create a
.env.example
file instead:.env
to.gitignore
:+.env
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"