Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
5 changes: 5 additions & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
PORT=5000
MONGO_URI=mongodb://localhost:27017/trading-auth
JWT_SECRET=your_jwt_secret


13 changes: 13 additions & 0 deletions backend/config/db.js
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("DB connection error:", err);
process.exit(1);
}
};

module.exports = connectDB;
55 changes: 55 additions & 0 deletions backend/controllers/auth.controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
const User = require('../models/user.model');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');

const JWT_SECRET = 'your_jwt_secret';

exports.registerUser = async (req, res) => {
const { email, password } = req.body;

try {
const userExists = await User.findOne({ email });
if (userExists) return res.status(400).json({ message: 'User already exists' });

const hashedPassword = await bcrypt.hash(password, 10);
const newUser = new User({ email, password: hashedPassword });
await newUser.save();

res.status(201).json({ message: 'User registered successfully' });
} catch (err) {
res.status(500).json({ message: 'Server error' });
}
};
exports.loginUser = async (req, res) => {
const { email, password } = req.body;

try {
const user = await User.findOne({ email });
if (!user) return res.status(401).json({ message: 'Invalid credentials' });

const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) return res.status(401).json({ message: 'Invalid credentials' });

const token = jwt.sign({ userId: user._id }, JWT_SECRET, { expiresIn: '1h' });

res.json({ token, message: 'Login successful' });
} catch (err) {
res.status(500).json({ message: 'Server error' });
}
};
exports.updatePassword = async (req, res) => {
const { email, newPassword } = req.body;

try {
const user = await User.findOne({ email });
if (!user) return res.status(404).json({ message: 'User not found' });

const hashedPassword = await bcrypt.hash(newPassword, 10);
user.password = hashedPassword;
await user.save();

res.json({ message: 'Password updated' });
} catch (err) {
res.status(500).json({ message: 'Server error' });
}
};
30 changes: 30 additions & 0 deletions backend/models/User.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');

const userSchema = new mongoose.Schema({
email: {
type: String,
required: true,
unique: true,
lowercase: true,
},
password: {
type: String,
required: true,
}
});
userSchema.pre('save', async function (next) {
if (!this.isModified('password')) {
return next();
}
const salt = await bcrypt.genSalt(10);
this.password = await bcrypt.hash(this.password, salt);
next();
});

userSchema.methods.matchPassword = async function (enteredPassword) {
return await bcrypt.compare(enteredPassword, this.password);
};

module.exports = mongoose.model('User', userSchema);

17 changes: 17 additions & 0 deletions backend/models/user.model.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const mongoose = require('mongoose');

const userSchema = new mongoose.Schema({
email: {
type: String,
required: true,
unique: true,
lowercase: true,
},
password: {
type: String,
required: true,
}
}, { timestamps: true });

module.exports = mongoose.model('User', userSchema);

12 changes: 12 additions & 0 deletions backend/routes/auth.routes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const express = require('express');
const router = express.Router();
const authController = require('../controllers/auth.controller');

router.post('/register', authController.registerUser);
router.post('/login', authController.loginUser);
router.post('/reset-password', authController.updatePassword);

module.exports = router;



23 changes: 23 additions & 0 deletions backend/routes/protectedRoutes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const express = require("express");
const jwt = require("jsonwebtoken");

const router = express.Router();

const verifyToken = (req, res, next) => {
const authHeader = req.headers["authorization"];
const token = authHeader && authHeader.split(" ")[1];

if (!token) return res.status(401).json({ message: "No token provided" });

jwt.verify(token, process.env.JWT_SECRET, (err, user) => {
if (err) return res.status(403).json({ message: "Invalid token" });
req.user = user;
next();
});
};

router.get("/", verifyToken, (req, res) => {
res.json({ message: "You have accessed a protected route", user: req.user });
});

module.exports = router;
14 changes: 14 additions & 0 deletions backend/routes/userRoutes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const express = require('express');
const router = express.Router();
const authMiddleware = require('../middleware/auth.middleware');

router.get('/profile', authMiddleware, async (req, res) => {
const user = req.user;
res.json({
id: user.id,
email: user.email,
fullName: user.fullName || 'N/A'
});
});

module.exports = router;
13 changes: 13 additions & 0 deletions backend/server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const express = require('express');
const dotenv = require('dotenv');
const connectDB = require('./config/db');
const authRoutes = require('./routes/auth.routes');

dotenv.config();
connectDB();
const app = express();
app.use(express.json());
app.use('/api/auth', authRoutes);

const PORT = process.env.PORT || 5000;
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
16 changes: 16 additions & 0 deletions node_modules/.bin/bcrypt

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions node_modules/.bin/bcrypt.cmd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 28 additions & 0 deletions node_modules/.bin/bcrypt.ps1

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions node_modules/.bin/node-gyp-build

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions node_modules/.bin/node-gyp-build-optional

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions node_modules/.bin/node-gyp-build-optional.cmd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 28 additions & 0 deletions node_modules/.bin/node-gyp-build-optional.ps1

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions node_modules/.bin/node-gyp-build-test

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions node_modules/.bin/node-gyp-build-test.cmd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 28 additions & 0 deletions node_modules/.bin/node-gyp-build-test.ps1

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading