Skip to content

Commit e9558bb

Browse files
Merge branch 'main' into dinesh
2 parents 5f035b2 + a6e708b commit e9558bb

24 files changed

Lines changed: 1398 additions & 600 deletions

.env.example

Lines changed: 0 additions & 1 deletion
This file was deleted.

backend/.env.sample

Lines changed: 0 additions & 3 deletions
This file was deleted.

backend/logger.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
const { createLogger, format, transports } = require('winston');
2+
const { combine, timestamp, printf, colorize, errors } = format;
3+
4+
const logFormat = printf(({ level, message, timestamp, stack }) => {
5+
const stackTrace = stack ? `\n${stack}` : '';
6+
return `${timestamp} ${level}: ${message}${stackTrace}`;
7+
});
8+
9+
const logger = createLogger({
10+
level: process.env.LOG_LEVEL || (process.env.NODE_ENV === 'production' ? 'info' : 'debug'),
11+
format: combine(errors({ stack: true }), timestamp(), logFormat),
12+
transports: [
13+
new transports.Console({ format: combine(errors({ stack: true }), colorize(), timestamp(), logFormat) }),
14+
],
15+
});
16+
17+
module.exports = logger;

backend/models/User.js

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,33 @@ const mongoose = require("mongoose");
22
const bcrypt = require("bcryptjs");
33

44
const UserSchema = new mongoose.Schema({
5-
username: {
6-
type: String,
7-
required: true,
8-
unique: true,
9-
},
10-
email: {
11-
type: String,
12-
required: true,
13-
unique: true,
14-
},
15-
password: {
16-
type: String,
17-
required: true,
18-
},
5+
username: {
6+
type: String,
7+
required: true,
8+
unique: true,
9+
},
10+
email: {
11+
type: String,
12+
required: true,
13+
unique: true,
14+
},
15+
password: {
16+
type: String,
17+
required: true,
18+
},
1919
});
2020

21+
// ✅ FIXED: no next()
2122
UserSchema.pre('save', async function () {
22-
if (!this.isModified('password'))
23-
return;
23+
if (!this.isModified('password')) return;
2424

25-
const salt = await bcrypt.genSalt(10);
26-
this.password = await bcrypt.hash(this.password, salt);
25+
const salt = await bcrypt.genSalt(10);
26+
this.password = await bcrypt.hash(this.password, salt);
2727
});
2828

29-
// Compare passwords during login
29+
// ✅ password comparison
3030
UserSchema.methods.comparePassword = async function (enteredPassword) {
31-
return await bcrypt.compare(enteredPassword, this.password);
31+
return bcrypt.compare(enteredPassword, this.password);
3232
};
3333

34-
module.exports = mongoose.model("User", UserSchema);
34+
module.exports = mongoose.model("User", UserSchema);

backend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
"dev": "nodemon server.js",
77
"start": "node server.js",
88
"test": "jasmine spec/**/*.spec.cjs"
9-
109
},
1110
"keywords": [],
1211
"author": "",
@@ -22,6 +21,7 @@
2221
"mongoose": "^8.8.2",
2322
"passport": "^0.7.0",
2423
"passport-local": "^1.0.0",
24+
"winston": "^3.19.0",
2525
"zod": "^4.4.3"
2626
},
2727
"devDependencies": {

backend/server.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ const cors = require('cors');
99
// Passport configuration
1010
require('./config/passportConfig');
1111

12+
const logger = require('./logger');
13+
1214
const app = express();
1315

1416
// CORS configuration
@@ -30,10 +32,10 @@ app.use('/api/auth', authRoutes);
3032

3133
// Connect to MongoDB
3234
mongoose.connect(process.env.MONGO_URI, {}).then(() => {
33-
console.log('Connected to MongoDB');
35+
logger.info('Connected to MongoDB');
3436
app.listen(process.env.PORT, () => {
35-
console.log(`Server running on port ${process.env.PORT}`);
37+
logger.info(`Server running on port ${process.env.PORT}`);
3638
});
3739
}).catch((err) => {
38-
console.log('MongoDB connection error:', err);
40+
logger.error('MongoDB connection error', err);
3941
});

package.json

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
"test:backend": "jasmine spec/**/*.spec.cjs",
1212
"preview": "vite preview",
1313
"docker:dev": "docker compose --profile dev up --build",
14-
"docker:prod": "docker compose --profile prod up -d --build"
14+
"docker:prod": "docker compose --profile prod up -d --build",
15+
"test": "jasmine"
1516
},
1617
"dependencies": {
1718
"@emotion/react": "^11.11.3",
@@ -21,15 +22,18 @@
2122
"@primer/octicons-react": "^19.25.0",
2223
"@vitejs/plugin-react": "^4.3.3",
2324
"axios": "^1.7.7",
25+
"express": "^5.2.1",
2426
"framer-motion": "^12.23.12",
2527
"lucide-react": "^0.525.0",
28+
"mongoose": "^9.6.2",
2629
"octokit": "^4.0.2",
2730
"postcss": "^8.4.47",
2831
"react": "^18.3.1",
2932
"react-dom": "^18.3.1",
3033
"react-hot-toast": "^2.4.1",
3134
"react-icons": "^5.3.0",
3235
"react-router-dom": "^6.28.0",
36+
"recharts": "^3.8.1",
3337
"tailwindcss": "^3.4.14"
3438
},
3539
"devDependencies": {
@@ -45,13 +49,21 @@
4549
"@types/react-router-dom": "^5.3.3",
4650
"@vitejs/plugin-react-swc": "^3.5.0",
4751
"autoprefixer": "^10.4.20",
48-
"bcryptjs": "^3.0.2",
52+
"bcryptjs": "^3.0.3",
4953
"eslint": "^9.13.0",
5054
"eslint-plugin-react": "^7.37.2",
5155
"eslint-plugin-react-hooks": "^5.0.0",
5256
"eslint-plugin-react-refresh": "^0.4.14",
57+
"express": "^5.2.1",
5358
"express-session": "^1.18.2",
5459
"globals": "^15.11.0",
60+
"jasmine": "^5.9.0",
61+
"mongoose": "^9.6.2",
62+
"passport": "^0.7.0",
63+
"passport-local": "^1.0.0",
64+
"supertest": "^7.1.4",
65+
"typescript-eslint": "^8.59.3",
66+
"vite": "^5.4.10",
5567
"jasmine": "^5.13.0",
5668
"jasmine-spec-reporter": "^7.0.0",
5769
"jsdom": "^29.1.1",

spec/auth.routes.spec.cjs

Lines changed: 79 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,32 @@ const express = require('express');
33
const request = require('supertest');
44
const session = require('express-session');
55
const passport = require('passport');
6+
67
const User = require('../backend/models/User');
78
const authRoutes = require('../backend/routes/auth');
89

9-
// Setup Express app for testing
10+
// Create test app
1011
function createTestApp() {
1112
const app = express();
13+
1214
app.use(express.json());
13-
app.use(session({ secret: 'test', resave: false, saveUninitialized: false }));
15+
16+
app.use(
17+
session({
18+
secret: 'test-secret',
19+
resave: false,
20+
saveUninitialized: false,
21+
})
22+
);
23+
1424
app.use(passport.initialize());
1525
app.use(passport.session());
26+
27+
// Load passport config AFTER initializing passport
1628
require('../backend/config/passportConfig');
29+
1730
app.use('/auth', authRoutes);
31+
1832
return app;
1933
}
2034

@@ -27,76 +41,107 @@ describe('Auth Routes', () => {
2741
});
2842

2943
afterAll(async () => {
30-
await mongoose.connection.db.dropDatabase();
31-
await mongoose.disconnect();
44+
if (mongoose.connection.readyState === 1) {
45+
await mongoose.connection.db.dropDatabase();
46+
await mongoose.disconnect();
47+
}
3248
});
3349

3450
afterEach(async () => {
3551
await User.deleteMany({});
3652
});
3753

54+
// ---------------- SIGNUP ----------------
3855
it('should sign up a new user', async () => {
3956
const res = await request(app)
4057
.post('/auth/signup')
41-
.send({ username: 'testuser', email: 'test@example.com', password: 'password123' });
58+
.send({
59+
username: 'testuser',
60+
email: 'test@example.com',
61+
password: 'password123',
62+
});
63+
4264
expect(res.status).toBe(201);
4365
expect(res.body.message).toBe('User created successfully');
66+
4467
const user = await User.findOne({ email: 'test@example.com' });
4568
expect(user).toBeTruthy();
4669
});
4770

4871
it('should not sign up a user with existing email', async () => {
49-
await new User({ username: 'testuser', email: 'test@example.com', password: 'password123' }).save();
50-
const res = await request(app)
51-
.post('/auth/signup')
52-
.send({ username: 'testuser2', email: 'test@example.com', password: 'password456' });
53-
expect(res.status).toBe(400);
54-
expect(res.body.message).toBe('User already exists');
55-
});
72+
await User.create({
73+
username: 'testuser',
74+
email: 'test@example.com',
75+
password: 'password123',
76+
});
5677

57-
it('should not sign up a user with existing username', async () => {
58-
await new User({ username: 'testuser', email: 'test@example.com', password: 'password123' }).save();
5978
const res = await request(app)
6079
.post('/auth/signup')
61-
.send({ username: 'testuser', email: 'test2@example.com', password: 'password456' });
80+
.send({
81+
username: 'testuser2',
82+
email: 'test@example.com',
83+
password: 'password456',
84+
});
85+
6286
expect(res.status).toBe(400);
6387
expect(res.body.message).toBe('User already exists');
6488
});
6589

90+
// ---------------- LOGIN ----------------
6691
it('should login a user with correct credentials', async () => {
67-
await request(app)
68-
.post('/auth/signup')
69-
.send({ username: 'testuser', email: 'test@example.com', password: 'password123' });
92+
await User.create({
93+
username: 'testuser',
94+
email: 'test@example.com',
95+
password: 'password123',
96+
});
97+
7098
const agent = request.agent(app);
71-
const res = await agent
72-
.post('/auth/login')
73-
.send({ email: 'test@example.com', password: 'password123' });
99+
100+
const res = await agent.post('/auth/login').send({
101+
email: 'test@example.com',
102+
password: 'password123',
103+
});
104+
74105
expect(res.status).toBe(200);
75106
expect(res.body.message).toBe('Login successful');
76107
expect(res.body.user.email).toBe('test@example.com');
77108
});
78109

79110
it('should not login a user with wrong password', async () => {
80-
await request(app)
81-
.post('/auth/signup')
82-
.send({ username: 'testuser', email: 'test@example.com', password: 'password123' });
111+
await User.create({
112+
username: 'testuser',
113+
email: 'test@example.com',
114+
password: 'password123',
115+
});
116+
83117
const agent = request.agent(app);
84-
const res = await agent
85-
.post('/auth/login')
86-
.send({ email: 'test@example.com', password: 'wrongpassword' });
118+
119+
const res = await agent.post('/auth/login').send({
120+
email: 'test@example.com',
121+
password: 'wrongpassword',
122+
});
123+
87124
expect(res.status).toBe(401);
88125
});
89126

127+
// ---------------- LOGOUT ----------------
90128
it('should logout a logged-in user', async () => {
91-
await request(app)
92-
.post('/auth/signup')
93-
.send({ username: 'testuser', email: 'test@example.com', password: 'password123' });
94129
const agent = request.agent(app);
95-
await agent
96-
.post('/auth/login')
97-
.send({ email: 'test@example.com', password: 'password123' });
130+
131+
await agent.post('/auth/signup').send({
132+
username: 'testuser',
133+
email: 'test@example.com',
134+
password: 'password123',
135+
});
136+
137+
await agent.post('/auth/login').send({
138+
email: 'test@example.com',
139+
password: 'password123',
140+
});
141+
98142
const res = await agent.get('/auth/logout');
143+
99144
expect(res.status).toBe(200);
100145
expect(res.body.message).toBe('Logged out successfully');
101146
});
102-
});
147+
});

0 commit comments

Comments
 (0)