diff --git a/.env.example b/.env.example index 0135353..5e9f7b0 100644 --- a/.env.example +++ b/.env.example @@ -1,3 +1,15 @@ NODE_ENV=development PORT=5000 + +# MongoDB Connection String +# For local MongoDB (if installed): +# MONGO_URI=mongodb://localhost:27017/intel-iot-club + +# For MongoDB Atlas (cloud): +# MONGO_URI=mongodb+srv://username:password@cluster.mongodb.net/intel-iot-club?retryWrites=true&w=majority +# Make sure to: +# 1. Replace 'username' and 'password' with your actual credentials +# 2. Replace 'cluster' with your actual cluster name +# 3. Whitelist your IP in MongoDB Atlas Network Access (or use 0.0.0.0/0 for testing) + MONGO_URI=your-mongodb-uri-here diff --git a/config/db.js b/config/db.js index ece84e9..d2f43f0 100644 --- a/config/db.js +++ b/config/db.js @@ -3,12 +3,44 @@ import mongoose from 'mongoose'; import { ENV } from './env.js'; export async function connectDB() { + // Check if using local MongoDB or Atlas + const isLocalMongo = ENV.MONGO_URI.includes('localhost') || ENV.MONGO_URI.includes('127.0.0.1'); + try { - const conn = await mongoose.connect(ENV.MONGO_URI); + // MongoDB connection options + const options = { + retryWrites: true, + w: 'majority', + serverSelectionTimeoutMS: 10000, + socketTimeoutMS: 45000, + }; + + // For Atlas connections, try with explicit TLS settings + if (!isLocalMongo) { + // Try to disable strict SSL verification (development only) + options.tls = true; + options.tlsAllowInvalidCertificates = true; + options.tlsAllowInvalidHostnames = true; + } + + console.log('šŸ”„ Connecting to MongoDB...'); + const conn = await mongoose.connect(ENV.MONGO_URI, options); console.log(`āœ… MongoDB connected: ${conn.connection.host}`); } catch (err) { console.error('āŒ MongoDB connection failed:', err.message); - // Optional: retry logic/backoff could go here for production + console.error('\nšŸ“‹ Troubleshooting steps:'); + console.error('1. Verify your MONGO_URI in .env file'); + console.error('2. Ensure your IP is whitelisted in MongoDB Atlas (Network Access)'); + console.error('3. Check if your connection string uses mongodb+srv:// format'); + console.error('4. Verify your MongoDB Atlas username/password are correct'); + console.error('5. Try using 0.0.0.0/0 in Network Access for testing\n'); + + if (err.message.includes('SSL') || err.message.includes('TLS')) { + console.error('āš ļø SSL/TLS Error detected. This usually means:'); + console.error(' - Your IP address is not whitelisted in MongoDB Atlas'); + console.error(' - Or there\'s a network/firewall issue\n'); + } + process.exit(1); } } diff --git a/controllers/eventController.js b/controllers/eventController.js index ff05ac6..d201846 100644 --- a/controllers/eventController.js +++ b/controllers/eventController.js @@ -2,37 +2,37 @@ import Event from '../models/Event.js'; // Get all events export const getEvent = async (req, res) => { - try { - const events = await Event.find().sort({ date: -1 }); // ← sort by date DESCENDING - if(!events || events.length === 0) { - return res.status(404).json({ message: 'No events found' });} - res.status(200).json(events); - } catch (error) { - res.status(500).json({ message: 'Error fetching events', error: error.message }); - } + try { + const events = await Event.find().sort({ date: -1 }); // ← sort by date DESCENDING + // Return empty array if no events, not a 404 + res.status(200).json(events); + } catch (error) { + res.status(500).json({ message: 'Error fetching events', error: error.message }); + } }; //Add a new event export const addEvent = async (req, res) => { - try{ - const newEvent = new Event(req.body); - await newEvent.save(); - if(!newEvent) { - return res.status(400).json({ message: 'Error adding event' }); - } - res.status(201).json({ message: 'Event added successfully' });} - catch (err) { - res.status(500).json({ message: 'Error adding event', error: err }); - } + try { + const newEvent = new Event(req.body); + await newEvent.save(); + if (!newEvent) { + return res.status(400).json({ message: 'Error adding event' }); + } + res.status(201).json({ message: 'Event added successfully' }); + } + catch (err) { + res.status(500).json({ message: 'Error adding event', error: err }); + } }; //Edit a specific event -export const editEvent = async(req, res) => { - try { - const updatedEvent = await Event.findByIdAndUpdate(req.params.id, req.body, { new: true }); - if (!updatedEvent) return res.status(404).json({ message: 'Event not found' }); - res.json({ message: 'Event updated successfully', event: updatedEvent }); +export const editEvent = async (req, res) => { + try { + const updatedEvent = await Event.findByIdAndUpdate(req.params.id, req.body, { new: true }); + if (!updatedEvent) return res.status(404).json({ message: 'Event not found' }); + res.json({ message: 'Event updated successfully', event: updatedEvent }); } catch (err) { res.status(500).json({ message: 'Error updating event', error: err }); } @@ -40,13 +40,13 @@ export const editEvent = async(req, res) => { //Delete a specific event export const deleteEvent = async (req, res) => { - try { - const deletedEvent = await Event.findByIdAndDelete(req.params.id); - if (!deletedEvent) return res.status(404).json({ message: 'Event not found' }); - res.json({ message: 'Event deleted successfully' }); - } catch (err) { - res.status(500).json({ message: 'Error deleting event', error: err }); - } + try { + const deletedEvent = await Event.findByIdAndDelete(req.params.id); + if (!deletedEvent) return res.status(404).json({ message: 'Event not found' }); + res.json({ message: 'Event deleted successfully' }); + } catch (err) { + res.status(500).json({ message: 'Error deleting event', error: err }); + } }; @@ -60,7 +60,7 @@ export const searchEvents = async (req, res) => { const events = await Event.find({ name: { $regex: title, $options: 'i' } // case-insensitive search - }).sort({date:-1}); + }).sort({ date: -1 }); if (events.length === 0) { return res.status(404).json({ message: 'No events found matching the title' }); diff --git a/controllers/membersController.js b/controllers/membersController.js index 10cf87a..5a49022 100644 --- a/controllers/membersController.js +++ b/controllers/membersController.js @@ -3,31 +3,29 @@ import Member from "../models/Member.js" //Get all members export const getMember = async (req, res) => { try { - const members = await Member.find(); - if(!members || members.length === 0) { - return res.status(404).json({ message: 'No members found' }); - } - res.status(200).json(members); + const members = await Member.find(); + // Return empty array if no members, not a 404 + res.status(200).json(members); } catch (err) { - res.status(500).json({ message: 'Error fetching members', error: err.message }); + res.status(500).json({ message: 'Error fetching members', error: err.message }); } } // Add a new member export const addMember = async (req, res) => { try { - const newMember = new Member(req.body); - await newMember.save(); - res.status(201).json({ message: 'Member added successfully' }); + const newMember = new Member(req.body); + await newMember.save(); + res.status(201).json({ message: 'Member added successfully' }); } catch (err) { - res.status(500).json({ message: 'Error adding member', error: err.message }); + res.status(500).json({ message: 'Error adding member', error: err.message }); } } // Edit a member export const editMember = async (req, res) => { - try { + try { const updatedMember = await Member.findByIdAndUpdate(req.params.id, req.body, { new: true }); if (!updatedMember) return res.status(404).json({ message: 'Member not found' }); res.json({ message: 'Member updated successfully', member: updatedMember }); @@ -38,11 +36,11 @@ export const editMember = async (req, res) => { // Delete a member export const deleteMember = async (req, res) => { - try { - const deletedMember = await Member.findByIdAndDelete(req.params.id); - if (!deletedMember) return res.status(404).json({ message: 'Member not found' }); - res.json({ message: 'Member deleted successfully' }); - } catch (err) { - res.status(500).json({ message: 'Error deleting member', error: err }); - } + try { + const deletedMember = await Member.findByIdAndDelete(req.params.id); + if (!deletedMember) return res.status(404).json({ message: 'Member not found' }); + res.json({ message: 'Member deleted successfully' }); + } catch (err) { + res.status(500).json({ message: 'Error deleting member', error: err }); + } } \ No newline at end of file diff --git a/package.json b/package.json index 4220842..c8e4abb 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,8 @@ "type": "module", "scripts": { "start": "node server.js", - "dev": "cross-env NODE_ENV=development nodemon server.js" + "dev": "cross-env NODE_ENV=development nodemon server.js", + "seed": "node scripts/seedDatabase.js" }, "keywords": [ "express", @@ -22,7 +23,9 @@ "cors": "^2.8.5", "dotenv": "^16.4.7", "express": "^4.21.2", - "mongoose": "^8.9.0" + "mongodb": "^7.0.0", + "mongoose": "^8.9.0", + "nodemailer": "^7.0.12" }, "devDependencies": { "cross-env": "^10.1.0", @@ -31,4 +34,4 @@ "engines": { "node": ">=18.0.0" } -} +} \ No newline at end of file diff --git a/scripts/seedDatabase.js b/scripts/seedDatabase.js new file mode 100644 index 0000000..f8613f8 --- /dev/null +++ b/scripts/seedDatabase.js @@ -0,0 +1,258 @@ +import mongoose from 'mongoose'; +import { ENV } from '../config/env.js'; +import Event from '../models/Event.js'; +import Project from '../models/Project.js'; +import Member from '../models/Member.js'; +import Timeline_events from '../models/Timeline_Events.js'; + +// Sample Events +const sampleEvents = [ + { + name: "IoT Workshop: Getting Started with Arduino", + date: "2024-02-15", + time: "10:00 AM - 2:00 PM", + location: "Tech Lab, Building A", + description: "Learn the basics of IoT development with Arduino. Hands-on workshop covering sensors, actuators, and basic programming.", + image: "https://images.unsplash.com/photo-1518770660439-4636190af475?w=800" + }, + { + name: "Smart Home Automation Hackathon", + date: "2024-03-20", + time: "9:00 AM - 6:00 PM", + location: "Innovation Center", + description: "24-hour hackathon focused on building smart home solutions using IoT devices and cloud platforms.", + image: "https://images.unsplash.com/photo-1558002038-1055907df827?w=800" + }, + { + name: "Guest Lecture: Future of IoT in Healthcare", + date: "2024-04-10", + time: "3:00 PM - 5:00 PM", + location: "Auditorium Hall", + description: "Industry expert discusses the transformative role of IoT in modern healthcare systems and medical devices.", + image: "https://images.unsplash.com/photo-1576091160399-112ba8d25d1d?w=800" + }, + { + name: "Raspberry Pi Project Showcase", + date: "2024-05-05", + time: "11:00 AM - 4:00 PM", + location: "Exhibition Hall", + description: "Students showcase their innovative Raspberry Pi projects ranging from home automation to robotics.", + image: "https://images.unsplash.com/photo-1553406830-ef2513450d76?w=800" + }, + { + name: "IoT Security Workshop", + date: "2024-06-12", + time: "2:00 PM - 5:00 PM", + location: "Cyber Security Lab", + description: "Learn about security challenges in IoT and best practices for securing connected devices.", + image: "https://images.unsplash.com/photo-1563986768609-322da13575f3?w=800" + } +]; + +// Sample Projects +const sampleProjects = [ + { + title: "Smart Irrigation System", + description: "An IoT-based automated irrigation system using soil moisture sensors and weather API integration to optimize water usage in agriculture.", + tags: ["IoT", "Arduino", "Sensors", "Agriculture"], + github: "https://github.com/intel-iot-club/smart-irrigation", + demo: "https://smart-irrigation-demo.netlify.app" + }, + { + title: "Home Energy Monitor", + description: "Real-time energy consumption monitoring system with mobile app integration for tracking and reducing household electricity usage.", + tags: ["ESP32", "Energy", "Mobile App", "Cloud"], + github: "https://github.com/intel-iot-club/energy-monitor", + demo: "https://energy-monitor-demo.netlify.app" + }, + { + title: "Air Quality Tracker", + description: "Multi-sensor air quality monitoring device that tracks PM2.5, CO2, temperature, and humidity with data visualization dashboard.", + tags: ["Raspberry Pi", "Sensors", "Data Viz", "Health"], + github: "https://github.com/intel-iot-club/air-quality", + demo: "https://air-quality-demo.netlify.app" + }, + { + title: "Smart Parking System", + description: "Ultrasonic sensor-based parking slot detection system with real-time availability updates via web and mobile interfaces.", + tags: ["IoT", "Ultrasonic", "Web App", "Smart City"], + github: "https://github.com/intel-iot-club/smart-parking", + demo: "https://smart-parking-demo.netlify.app" + }, + { + title: "Automated Plant Care", + description: "Intelligent plant monitoring system that automatically waters plants based on soil moisture and provides growth analytics.", + tags: ["Arduino", "Automation", "ML", "Agriculture"], + github: "https://github.com/intel-iot-club/plant-care", + demo: "https://plant-care-demo.netlify.app" + } +]; + +// Sample Members +const sampleMembers = [ + { + name: "Rajesh Kumar", + role: ["President", "Core Team"], + bio: "Passionate about IoT and embedded systems. Leading the club towards innovation in smart technology.", + image: "https://i.pravatar.cc/300?img=12", + github: "https://github.com/rajeshkumar", + linkedin: "https://linkedin.com/in/rajeshkumar", + email: "rajesh@example.com" + }, + { + name: "Priya Sharma", + role: ["Vice President", "Core Team"], + bio: "IoT enthusiast with expertise in cloud platforms and data analytics. Focused on building scalable IoT solutions.", + image: "https://i.pravatar.cc/300?img=45", + github: "https://github.com/priyasharma", + linkedin: "https://linkedin.com/in/priyasharma", + email: "priya@example.com" + }, + { + name: "Arjun Patel", + role: ["Technical Lead", "Core Team"], + bio: "Hardware hacker and maker. Specializes in Arduino, Raspberry Pi, and sensor integration.", + image: "https://i.pravatar.cc/300?img=33", + github: "https://github.com/arjunpatel", + linkedin: "https://linkedin.com/in/arjunpatel", + email: "arjun@example.com" + }, + { + name: "Sneha Reddy", + role: ["Events Coordinator", "Core Team"], + bio: "Organizing workshops and hackathons to spread IoT knowledge. Passionate about community building.", + image: "https://i.pravatar.cc/300?img=47", + github: "https://github.com/snehareddy", + linkedin: "https://linkedin.com/in/snehareddy", + email: "sneha@example.com" + }, + { + name: "Vikram Singh", + role: ["Member"], + bio: "Working on smart home automation projects. Interested in ESP32 and home assistant integration.", + image: "https://i.pravatar.cc/300?img=15", + github: "https://github.com/vikramsingh", + linkedin: "https://linkedin.com/in/vikramsingh", + email: "vikram@example.com" + }, + { + name: "Ananya Iyer", + role: ["Member"], + bio: "Exploring IoT applications in healthcare. Building wearable health monitoring devices.", + image: "https://i.pravatar.cc/300?img=48", + github: "https://github.com/ananyaiyer", + linkedin: "https://linkedin.com/in/ananyaiyer", + email: "ananya@example.com" + } +]; + +// Sample Timeline Events +const sampleTimeline = [ + { + title: "Club Foundation", + date: new Date("2020-08-15"), + description: "Intel IoT Club was officially established at Amrita Vishwa Vidyapeetham with 15 founding members.", + image: "https://images.unsplash.com/photo-1511578314322-379afb476865?w=800", + isFirst: true + }, + { + title: "First Workshop", + date: new Date("2020-10-20"), + description: "Conducted our first Arduino workshop with over 50 participants learning the basics of IoT development.", + image: "https://images.unsplash.com/photo-1517245386807-bb43f82c33c4?w=800", + isFirst: false + }, + { + title: "Smart City Hackathon", + date: new Date("2021-03-15"), + description: "Organized a 24-hour hackathon focused on smart city solutions, with 20 teams participating.", + image: "https://images.unsplash.com/photo-1504384308090-c894fdcc538d?w=800", + isFirst: false + }, + { + title: "Industry Partnership", + date: new Date("2022-01-10"), + description: "Partnered with leading IoT companies for mentorship and project collaboration opportunities.", + image: "https://images.unsplash.com/photo-1556761175-b413da4baf72?w=800", + isFirst: false + }, + { + title: "100+ Members Milestone", + date: new Date("2023-06-01"), + description: "Reached 100+ active members, making us one of the largest technical clubs on campus.", + image: "https://images.unsplash.com/photo-1523580494863-6f3031224c94?w=800", + isFirst: false + } +]; + +async function connectWithRetry(maxRetries = 3) { + for (let i = 0; i < maxRetries; i++) { + try { + console.log(`šŸ”„ Connection attempt ${i + 1}/${maxRetries}...`); + + const options = { + retryWrites: true, + w: 'majority', + serverSelectionTimeoutMS: 10000, + socketTimeoutMS: 45000, + tls: true, + tlsAllowInvalidCertificates: true, + tlsAllowInvalidHostnames: true, + }; + + await mongoose.connect(ENV.MONGO_URI, options); + console.log('āœ… Connected to MongoDB\n'); + return true; + } catch (error) { + console.error(`āŒ Connection attempt ${i + 1} failed:`, error.message); + if (i < maxRetries - 1) { + console.log('ā³ Waiting 2 seconds before retry...\n'); + await new Promise(resolve => setTimeout(resolve, 2000)); + } + } + } + throw new Error('Failed to connect after multiple attempts'); +} + +async function seedDatabase() { + try { + // Connect to MongoDB with retry + await connectWithRetry(); + + // Clear existing data + console.log('šŸ—‘ļø Clearing existing data...'); + await Event.deleteMany({}); + await Project.deleteMany({}); + await Member.deleteMany({}); + await Timeline_events.deleteMany({}); + console.log('āœ… Cleared all collections\n'); + + // Insert sample data + console.log('šŸ“ Inserting sample data...\n'); + + await Event.insertMany(sampleEvents); + console.log(`āœ… Added ${sampleEvents.length} events`); + + await Project.insertMany(sampleProjects); + console.log(`āœ… Added ${sampleProjects.length} projects`); + + await Member.insertMany(sampleMembers); + console.log(`āœ… Added ${sampleMembers.length} members`); + + await Timeline_events.insertMany(sampleTimeline); + console.log(`āœ… Added ${sampleTimeline.length} timeline events`); + + console.log('\nšŸŽ‰ Database seeded successfully!'); + + // Close connection + await mongoose.connection.close(); + console.log('āœ… Connection closed'); + + process.exit(0); + } catch (error) { + console.error('āŒ Error seeding database:', error.message); + process.exit(1); + } +} + +seedDatabase(); diff --git a/scripts/seedEvents.js b/scripts/seedEvents.js new file mode 100644 index 0000000..0a9cd49 --- /dev/null +++ b/scripts/seedEvents.js @@ -0,0 +1,74 @@ +import mongoose from 'mongoose'; +import { ENV } from '../config/env.js'; +import Event from '../models/Event.js'; + +const sampleEvents = [ + { + name: "IoT Workshop: Getting Started with Arduino", + date: "2024-02-15", + time: "10:00 AM - 2:00 PM", + location: "Tech Lab, Building A", + description: "Learn the basics of IoT development with Arduino. Hands-on workshop covering sensors, actuators, and basic programming.", + image: "https://images.unsplash.com/photo-1518770660439-4636190af475?w=800" + }, + { + name: "Smart Home Automation Hackathon", + date: "2024-03-20", + time: "9:00 AM - 6:00 PM", + location: "Innovation Center", + description: "24-hour hackathon focused on building smart home solutions using IoT devices and cloud platforms.", + image: "https://images.unsplash.com/photo-1558002038-1055907df827?w=800" + }, + { + name: "Guest Lecture: Future of IoT in Healthcare", + date: "2024-04-10", + time: "3:00 PM - 5:00 PM", + location: "Auditorium Hall", + description: "Industry expert discusses the transformative role of IoT in modern healthcare systems and medical devices.", + image: "https://images.unsplash.com/photo-1576091160399-112ba8d25d1d?w=800" + }, + { + name: "Raspberry Pi Project Showcase", + date: "2024-05-05", + time: "11:00 AM - 4:00 PM", + location: "Exhibition Hall", + description: "Students showcase their innovative Raspberry Pi projects ranging from home automation to robotics.", + image: "https://images.unsplash.com/photo-1553406830-ef2513450d76?w=800" + }, + { + name: "IoT Security Workshop", + date: "2024-06-12", + time: "2:00 PM - 5:00 PM", + location: "Cyber Security Lab", + description: "Learn about security challenges in IoT and best practices for securing connected devices.", + image: "https://images.unsplash.com/photo-1563986768609-322da13575f3?w=800" + } +]; + +async function seedDatabase() { + try { + // Connect to MongoDB + await mongoose.connect(ENV.MONGO_URI); + console.log('āœ… Connected to MongoDB'); + + // Clear existing events + await Event.deleteMany({}); + console.log('šŸ—‘ļø Cleared existing events'); + + // Insert sample events + await Event.insertMany(sampleEvents); + console.log(`āœ… Added ${sampleEvents.length} sample events`); + + console.log('\nšŸ“‹ Sample events added:'); + sampleEvents.forEach((event, index) => { + console.log(`${index + 1}. ${event.name} - ${event.date}`); + }); + + process.exit(0); + } catch (error) { + console.error('āŒ Error seeding database:', error); + process.exit(1); + } +} + +seedDatabase();