Skip to content
Merged
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion backend/.env
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
PORT=5000
MONGO_URI=mongodb://localhost:27017/eventhub
MONGO_URI="mongodb://127.0.0.1:27017/eventhub"
2 changes: 1 addition & 1 deletion backend/config/database.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import mongoose from 'mongoose';

const connectDB = async () => {
try {
const conn = await mongoose.connect(process.env.MONGO_URI || 'mongodb://localhost:27017/eventhub');
const conn = await mongoose.connect(process.env.MONGO_URI || 'mongodb+srv://eventhub:<eventhub123>@eventhub.hiegdlh.mongodb.net/?appName=eventhub');
console.log(`MongoDB Connected: ${conn.connection.host}`);
} catch (error) {
console.error(`Error connecting to MongoDB: ${error.message}`);
Expand Down
96 changes: 96 additions & 0 deletions backend/controllers/authController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import User from '../models/User.js';
import jwt from 'jsonwebtoken';

const generateToken = (id) => {
return jwt.sign({ id }, process.env.JWT_SECRET || 'fallback_secret', {
expiresIn: '1d',
});
};

// @desc Register a new user
// @route POST /api/auth/register
// @access Public
export const registerUser = async (req, res) => {
try {
const { name, email, password } = req.body;

if (!name || !email || !password) {
return res.status(400).json({ message: 'Please provide all fields' });
}

const userExists = await User.findOne({ email });

if (userExists) {
return res.status(400).json({ message: 'User already exists with this email' });
}

const user = await User.create({
name,
email,
password,
});

if (user) {
res.status(201).json({
message: 'Registration successful',
_id: user._id,
name: user.name,
email: user.email,
role: user.role,
token: generateToken(user._id),
});
} else {
res.status(400).json({ message: 'Invalid user data' });
}
} catch (error) {
res.status(500).json({ message: error.message || 'Server Error' });
}
};

// @desc Auth user & get token
// @route POST /api/auth/login
// @access Public
export const loginUser = async (req, res) => {
try {
const { email, password } = req.body;

const user = await User.findOne({ email });

if (user && (await user.matchPassword(password))) {
res.json({
message: 'Login successful',
_id: user._id,
name: user.name,
email: user.email,
role: user.role,
token: generateToken(user._id),
});
} else {
res.status(401).json({ message: 'Invalid email or password' });
}
} catch (error) {
res.status(500).json({ message: error.message || 'Server Error' });
}
};

// @desc Get user profile
// @route GET /api/auth/profile
// @access Private
export const getUserProfile = async (req, res) => {
try {
const user = await User.findById(req.user._id);

if (user) {
res.json({
_id: user._id,
name: user.name,
email: user.email,
role: user.role,
});
} else {
res.status(404).json({ message: 'User not found' });
}
} catch (error) {
res.status(500).json({ message: error.message || 'Server Error' });
}
};
27 changes: 27 additions & 0 deletions backend/middleware/authMiddleware.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import jwt from 'jsonwebtoken';
import User from '../models/User.js';

export const protect = async (req, res, next) => {
let token;

if (
req.headers.authorization &&
req.headers.authorization.startsWith('Bearer')
) {
try {
token = req.headers.authorization.split(' ')[1];

const decoded = jwt.verify(token, process.env.JWT_SECRET || 'fallback_secret');

req.user = await User.findById(decoded.id).select('-password');

next();
} catch (error) {
res.status(401).json({ message: 'Not authorized, token failed' });
}
}

if (!token) {
res.status(401).json({ message: 'Not authorized, no token' });
}
};
46 changes: 46 additions & 0 deletions backend/models/User.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import mongoose from 'mongoose';
import bcrypt from 'bcrypt';

const userSchema = new mongoose.Schema(
{
name: {
type: String,
required: true,
},
email: {
type: String,
required: true,
unique: true,
},
password: {
type: String,
required: true,
},
role: {
type: String,
enum: ['user', 'admin'],
default: 'user',
},
},
{
timestamps: true,
}
);

// Hash password before saving
userSchema.pre('save', async function (next) {
if (!this.isModified('password')) {
next();
}
const salt = await bcrypt.genSalt(10);
this.password = await bcrypt.hash(this.password, salt);
});

// Match user entered password to hashed password in database
userSchema.methods.matchPassword = async function (enteredPassword) {
return await bcrypt.compare(enteredPassword, this.password);
};

const User = mongoose.model('User', userSchema);

export default User;
11 changes: 11 additions & 0 deletions backend/routes/authRoutes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import express from 'express';
import { registerUser, loginUser, getUserProfile } from '../controllers/authController.js';
import { protect } from '../middleware/authMiddleware.js';

const router = express.Router();

router.post('/register', registerUser);
router.post('/login', loginUser);
router.get('/profile', protect, getUserProfile);

export default router;
12 changes: 10 additions & 2 deletions backend/seed.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import mongoose from 'mongoose';
import dotenv from 'dotenv';
import Event from './models/Event.js';
import User from './models/User.js';

dotenv.config();

Expand Down Expand Up @@ -94,10 +95,17 @@ const seedDB = async () => {

// Clear existing events to prevent duplicates, if you prefer not to clear them you can remove this
await Event.deleteMany({});
console.log('Cleared existing events');
await User.deleteMany({});
console.log('Cleared existing events and users');

await Event.insertMany(events);
console.log('Database seeded with 8 dummy events!');
await User.create({
name: 'Test Administrator',
email: 'test@example.com',
password: 'password123',
role: 'admin'
});
console.log('Database seeded with 8 dummy events and 1 test user!');

process.exit(0);
} catch (error) {
Expand Down
2 changes: 2 additions & 0 deletions backend/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import cors from 'cors';
import connectDB from './config/database.js';
import eventRoutes from './routes/eventRoutes.js';
import bookingRoutes from './routes/bookingRoutes.js';
import authRoutes from './routes/authRoutes.js';

// Load environment variables
dotenv.config();
Expand All @@ -20,6 +21,7 @@ app.use(express.json());
// Routes
app.use('/api/events', eventRoutes);
app.use('/api/bookings', bookingRoutes);
app.use('/api/auth', authRoutes);

// Base route for testing
app.get('/', (req, res) => {
Expand Down
Loading
Loading