diff --git a/server/.gitignore b/server/.gitignore new file mode 100644 index 00000000..a0add908 --- /dev/null +++ b/server/.gitignore @@ -0,0 +1,3 @@ +node_modules +.env +yarn.lock \ No newline at end of file diff --git a/server/index.js b/server/index.js new file mode 100644 index 00000000..b92b52c9 --- /dev/null +++ b/server/index.js @@ -0,0 +1,36 @@ +import { mongoConnect } from './schema/mongo.connect.js'; +import { cfpRouter } from './src/cpfs/cfp.router.js'; +import { eventRouter } from './src/events/events.router.js'; +import { hackathonRouter } from './src/hackathons/hackathon.router.js'; +import { userRouter } from './src/users/user.router.js'; +import cors from 'cors'; +import dotenv from 'dotenv'; +import express from 'express'; + +dotenv.config(); +const app = express(); +const port = process.env.PORT; + +const allowedOrigins = [`${process.env.UI_ENDPOINT}`]; + +const options = { + origin: allowedOrigins, + credentials: true, +}; + +app.use(cors(options)); +await mongoConnect(); + +app.get('/', () => { + throw new Error(''); +}); + +app.use(express.json()); + +app.use('/api/user', userRouter); +app.use('/api/events', eventRouter); +app.use('/api/hackathons', hackathonRouter); +app.use('/api/cfps', cfpRouter); + +// eslint-disable-next-line no-console +app.listen(port, () => console.log(`server is running on ${port}`)); diff --git a/server/package.json b/server/package.json new file mode 100644 index 00000000..4c270f97 --- /dev/null +++ b/server/package.json @@ -0,0 +1,25 @@ +{ + "name": "opensource", + "version": "1.0.0", + "description": "", + "main": "index.js", + "type": "module", + "scripts": { + "dev": "nodemon index.js", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "body-parser": "^1.20.2", + "cors": "^2.8.5", + "dotenv": "^16.3.1", + "eslint": "^8.43.0", + "express": "^4.18.2", + "http": "^0.0.1-security", + "husky": "^8.0.3", + "mongodb": "^5.6.0", + "mongoose": "^7.3.1", + "prettier": "^2.8.8" + } +} diff --git a/server/schema/cfps/CfpsSchema.js b/server/schema/cfps/CfpsSchema.js new file mode 100644 index 00000000..68c18031 --- /dev/null +++ b/server/schema/cfps/CfpsSchema.js @@ -0,0 +1,47 @@ +import { model, Schema } from 'mongoose'; + +const CfpsSchema = new Schema( + { + name: { + type: String, + require: true, + }, + slug: { + type: String, + require: true, + }, + organizer: { + type: String, + require: true, + }, + description: { + type: String, + require: true, + }, + address: { + type: { isOnline: Boolean, location: String }, + required: true, + }, + image: { + type: Buffer, + require: false, + }, + date: { + type: Date, + require: true, + }, + duration: { + type: Number, + require: true, + }, + tags: { + type: [String], + require: true, + }, + }, + { + timestamps: true, + } +); + +export const CfpModel = model('cfps', CfpsSchema); diff --git a/server/schema/events/EventsSchema.js b/server/schema/events/EventsSchema.js new file mode 100644 index 00000000..b00fe267 --- /dev/null +++ b/server/schema/events/EventsSchema.js @@ -0,0 +1,47 @@ +import { model, Schema } from 'mongoose'; + +const EventsSchema = new Schema( + { + name: { + type: String, + require: true, + }, + slug: { + type: String, + require: true, + }, + organizer: { + type: String, + require: true, + }, + description: { + type: String, + require: true, + }, + address: { + type: { isOnline: Boolean, location: String }, + required: true, + }, + image: { + type: Buffer, + require: false, + }, + date: { + type: Date, + require: true, + }, + duration: { + type: Number, + require: true, + }, + tags: { + type: [String], + require: true, + }, + }, + { + timestamps: true, + } +); + +export const EventModel = model('events', EventsSchema); diff --git a/server/schema/hackathon/hackathonSchema.js b/server/schema/hackathon/hackathonSchema.js new file mode 100644 index 00000000..bdee03b3 --- /dev/null +++ b/server/schema/hackathon/hackathonSchema.js @@ -0,0 +1,47 @@ +import { model, Schema } from 'mongoose'; + +const HackathonSchema = new Schema( + { + name: { + type: String, + require: true, + }, + slug: { + type: String, + require: true, + }, + organizer: { + type: String, + require: true, + }, + description: { + type: String, + require: true, + }, + address: { + type: { isOnline: Boolean, location: String }, + required: true, + }, + image: { + type: Buffer, + require: false, + }, + date: { + type: Date, + require: true, + }, + duration: { + type: Number, + require: true, + }, + tags: { + type: [String], + require: true, + }, + }, + { + timestamps: true, + } +); + +export const HackathonModel = model('hackathon', HackathonSchema); diff --git a/server/schema/mongo.connect.js b/server/schema/mongo.connect.js new file mode 100644 index 00000000..2ab8c1d8 --- /dev/null +++ b/server/schema/mongo.connect.js @@ -0,0 +1,23 @@ +import mongoose, { connect } from 'mongoose'; + +//surprass deprication warning +mongoose.set('strictQuery', false); + +export const mongoConnect = async () => { + const connectionString = + process.env.MONGODB_PROTO + + process.env.MONGODB_USER + + ':' + + process.env.MONGODB_PASSWORD + + '@' + + process.env.MONGODB_URL + + '/' + + process.env.MONGODB_DATABASE; + try { + // eslint-disable-next-line no-console + console.log('connection'); + await connect(connectionString); + } catch (error) { + throw new Error(error); + } +}; diff --git a/server/schema/user/UserSchema.js b/server/schema/user/UserSchema.js new file mode 100644 index 00000000..89a4bd9f --- /dev/null +++ b/server/schema/user/UserSchema.js @@ -0,0 +1,44 @@ +import { model, Schema } from 'mongoose'; + +const UserSchema = new Schema( + { + name: { + type: String, + require: true, + }, + email: { + type: String, + require: true, + }, + password: { + type: String, + require: true, + }, + image: { + type: Buffer, + require: false, + }, + bio: { + type: String, + require: false, + }, + role: { + type: String, + require: true, + }, + socials: { + type: [ + { + name: String, + link: String, + }, + ], + require: false, + }, + }, + { + timestamps: true, + } +); + +export const UserModel = model('user', UserSchema); diff --git a/server/src/cpfs/cfp.router.js b/server/src/cpfs/cfp.router.js new file mode 100644 index 00000000..78ca27fd --- /dev/null +++ b/server/src/cpfs/cfp.router.js @@ -0,0 +1,93 @@ +import { CfpService } from './cfp.service.js'; +import express from 'express'; + +export const cfpRouter = express.Router(); + +// get all cfps +cfpRouter.get('/', async (_, res) => { + try { + const cfps = await CfpService.getAllCfps(); + res.status(200).send({ success: true, cfps }); + } catch (error) { + res.status(500).json({ success: false, message: 'Internal server error' }); + } +}); + +// get cfp by id +cfpRouter.get('/id/:id', async (req, res) => { + try { + const { id } = req.params; + if (!id) { + res.status(422).send({ success: false, message: 'Invalid id parameter' }); + } + + const cfps = await CfpService.getCfpsById(id); + res.status(200).send({ success: true, cfps }); + } catch (error) { + res.status(500).json({ success: false, message: 'Internal server error' }); + } +}); + +// get cfp by slug +cfpRouter.get('/slug/:slug', async (req, res) => { + try { + const { slug } = req.params; + if (!slug) { + res + .status(422) + .send({ success: false, message: 'Invalid slug parameter' }); + } + + const cfps = await CfpService.getCfpsBySlug(slug); + res.status(200).send({ success: true, cfps }); + } catch (error) { + res.status(500).json({ success: false, message: 'Internal server error' }); + } +}); + +// add cfp +cfpRouter.post('/create', async (req, res) => { + try { + const { data } = req.body; + + if (!data) { + res.status(422).send({ success: false, message: 'Invalid data' }); + } + const cfps = await CfpService.createCfp(data); + res.status(200).send({ success: true, cfps }); + } catch (error) { + res.status(500).json({ success: false, message: 'Internal server error' }); + } +}); + +// update cfp +cfpRouter.post('/update/:id', async (req, res) => { + try { + const { id } = req.params; + const { data } = req.body; + if (!id) { + res.status(422).send({ success: false, message: 'Invalid id parameter' }); + } + if (!data) { + res.status(422).send({ success: false, message: 'Invalid data' }); + } + const cfps = await CfpService.updateCfp(id, data); + res.status(200).send({ success: true, cfps }); + } catch (error) { + res.status(500).json({ success: false, message: 'Internal server error' }); + } +}); + +// delete cfp by id +cfpRouter.post('/delete', async (req, res) => { + try { + const { id } = req.body; + if (!id) { + res.status(422).send({ success: false, message: 'Invalid id' }); + } + const cfps = await CfpService.deleteCfp(id); + res.status(200).send({ success: true, cfps }); + } catch (error) { + res.status(500).json({ success: false, message: 'Internal server error' }); + } +}); diff --git a/server/src/cpfs/cfp.service.js b/server/src/cpfs/cfp.service.js new file mode 100644 index 00000000..ac7fcf39 --- /dev/null +++ b/server/src/cpfs/cfp.service.js @@ -0,0 +1,69 @@ +import { CfpModel } from '../../schema/cfps/CfpsSchema.js'; + +const getAllCfps = async () => { + try { + const cfps = await CfpModel.find({}); + return cfps; + } catch (error) { + throw new Error(error); + } +}; + +const getCfpsById = async (_id) => { + try { + const cfps = await CfpModel.findById(_id); + return cfps; + } catch (error) { + throw new Error(error); + } +}; + +const getCfpsBySlug = async (slug) => { + try { + const cfps = await CfpModel.find({ slug }); + return cfps; + } catch (error) { + throw new Error(error); + } +}; + +const createCfp = async (eventInfo) => { + try { + const cfp = new CfpModel(eventInfo); + await cfp.save(); + return cfp; + } catch (error) { + throw new Error(error); + } +}; + +const updateCfp = async (_id, updatedValue) => { + try { + const cfps = await CfpModel.findByIdAndUpdate( + _id, + { $set: updatedValue }, + { new: true } + ); + return cfps; + } catch (error) { + throw new Error(error); + } +}; + +const deleteCfp = async (_id) => { + try { + const cfps = await CfpModel.deleteOne({ _id }); + return cfps; + } catch (error) { + throw new Error(error); + } +}; + +export const CfpService = { + getAllCfps, + getCfpsById, + getCfpsBySlug, + createCfp, + updateCfp, + deleteCfp, +}; diff --git a/server/src/events/event.service.js b/server/src/events/event.service.js new file mode 100644 index 00000000..8fe915c4 --- /dev/null +++ b/server/src/events/event.service.js @@ -0,0 +1,72 @@ +import { EventModel } from '../../schema/events/EventsSchema.js'; + +const getAllEvents = async () => { + try { + const eventData = await EventModel.find({}); + + return eventData; + } catch (error) { + throw new Error(error); + } +}; + +const getEventsById = async (_id) => { + try { + const eventById = await EventModel.find({ _id }); + return eventById; + } catch (error) { + throw new Error(error); + } +}; + +const getEventsBySlug = async (slug) => { + try { + const eventById = await EventModel.find({ slug }); + return eventById; + } catch (error) { + throw new Error(error); + } +}; + +const createEvent = async (eventInfo) => { + try { + const createdEvent = new EventModel(eventInfo); + + await createdEvent?.save(); + + return createdEvent; + } catch (error) { + throw new Error(error); + } +}; +const updateEvent = async (_id, updatedValue) => { + try { + const updatedEvent = await EventModel.findOneAndUpdate( + { _id: _id }, + { $set: updatedValue }, + { returnOriginal: false } + ); + + return updatedEvent; + } catch (error) { + throw new Error(error); + } +}; + +const deleteEvent = async (_id) => { + try { + const event = await EventModel.deleteOne({ _id: _id }); + return event; + } catch (error) { + throw new Error(error); + } +}; + +export const EventService = { + getAllEvents, + getEventsById, + getEventsBySlug, + createEvent, + updateEvent, + deleteEvent, +}; diff --git a/server/src/events/events.router.js b/server/src/events/events.router.js new file mode 100644 index 00000000..a7ef2e4c --- /dev/null +++ b/server/src/events/events.router.js @@ -0,0 +1,92 @@ +import { EventService } from './event.service.js'; +import express from 'express'; + +export const eventRouter = express.Router(); + +//get all events +eventRouter.get('/', async (_, res) => { + try { + const events = await EventService.getAllEvents(); + res.status(200).send({ success: true, events: events }); + } catch (error) { + res.status(500).json({ success: false, message: 'Internal server error' }); + } +}); + +//get event by id +eventRouter.get('/id/:id', async (req, res) => { + try { + const { id } = req.params; + if (!id) { + res.status(422).send({ success: false, message: 'Invalid id parameter' }); + } + + const events = await EventService.getEventsById(id); + res.status(200).send({ success: true, events: events }); + } catch (error) { + res.status(500).json({ success: false, message: 'Internal server error' }); + } +}); + +//get event by slug +eventRouter.get('/slug/:slug', async (req, res) => { + try { + const { slug } = req.params; + if (!slug) { + res + .status(422) + .send({ success: false, message: 'Invalid slug parameter' }); + } + const events = await EventService.getEventsBySlug(slug); + res.status(200).send({ success: true, events: events }); + } catch (error) { + res.status(500).json({ success: false, message: 'Internal server error' }); + } +}); + +//add event +eventRouter.post('/create', async (req, res) => { + try { + const { data } = req.body; + + if (!data) { + res.status(422).send({ success: false, message: 'Invalid data' }); + } + const events = await EventService.createEvent(data); + res.status(200).send({ success: true, events: events }); + } catch (error) { + res.status(500).json({ success: false, message: 'Internal server error' }); + } +}); +//update events +eventRouter.post('/update/:id', async (req, res) => { + try { + const { id } = req.params; + const { data } = req.body; + + if (!id) { + res.status(422).send({ success: false, message: 'Invalid id parameter' }); + } + if (!data) { + res.status(422).send({ success: false, message: 'Invalid data' }); + } + const events = await EventService.updateEvent(id, data); + res.status(200).send({ success: true, events: events }); + } catch (error) { + res.status(500).json({ success: false, message: 'Internal server error' }); + } +}); +//delete event by id + +eventRouter.post('/delete', async (req, res) => { + try { + const { id } = req.body; + if (!id) { + res.status(422).send({ success: false, message: 'Invalid id' }); + } + const events = await EventService.deleteEvent(id); + res.status(200).send({ success: true, events: events }); + } catch (error) { + res.status(500).json({ success: false, message: 'Internal server error' }); + } +}); diff --git a/server/src/hackathons/hackathon.router.js b/server/src/hackathons/hackathon.router.js new file mode 100644 index 00000000..5037a0b6 --- /dev/null +++ b/server/src/hackathons/hackathon.router.js @@ -0,0 +1,95 @@ +import { HackathonService } from './hackathon.service.js'; +import express from 'express'; + +export const hackathonRouter = express.Router(); + +//get all hackathon + +hackathonRouter.get('/', async (_, res) => { + try { + const hackathon = await HackathonService.getAllHackathons(); + res.status(200).send({ success: true, hackathon: hackathon }); + } catch (error) { + res.status(500).json({ success: false, message: 'Internal server error' }); + } +}); + +//get hackathon by id + +hackathonRouter.get('/id/:id', async (req, res) => { + try { + const { id } = req.params; + + if (!id) { + res.status(422).send({ success: false, message: 'Invalid id parameter' }); + } + + const hackathon = await HackathonService.getHackathonsById(id); + res.status(200).send({ success: true, hackathon: hackathon }); + } catch (error) { + res.status(500).json({ success: false, message: 'Internal server error' }); + } +}); + +//get hackathon by slug + +hackathonRouter.get('/slug/:slug', async (req, res) => { + try { + const { slug } = req.params; + if (!slug) { + res + .status(422) + .send({ success: false, message: 'Invalid slug parameter' }); + } + + const hackathon = await HackathonService.getHackathonsBySlug(slug); + res.status(200).send({ success: true, hackathon: hackathon }); + } catch (error) { + res.status(500).json({ success: false, message: 'Internal server error' }); + } +}); + +//create hackathon +hackathonRouter.post('/create', async (req, res) => { + try { + const { data } = req.body; + + if (!data) { + res.status(422).send({ success: false, message: 'Invalid data' }); + } + const hackathon = await HackathonService.createHackathon(data); + res.status(200).send({ success: true, hackathon: hackathon }); + } catch (error) { + res.status(500).json({ success: false, message: 'Internal server error' }); + } +}); + +//update hackathon +hackathonRouter.post('/update/:id', async (req, res) => { + try { + const { id } = req.params; + const { data } = req.body; + if (!id) { + res.status(422).send({ success: false, message: 'Invalid id parameter' }); + } + if (!data) { + res.status(422).send({ success: false, message: 'Invalid data' }); + } + const hackathon = await HackathonService.updateHackathon(id, data); + res.status(200).send({ success: true, hackathon: hackathon }); + } catch (error) { + res.status(500).json({ success: false, message: 'Internal server error' }); + } +}); + +//delete hackathon by id + +hackathonRouter.post('/delete', async (req, res) => { + try { + const { id } = req.body; + const hackathon = await HackathonService.deleteHackathon(id); + res.status(200).send({ success: true, hackathon: hackathon }); + } catch (error) { + res.status(500).json({ success: false, message: 'Internal server error' }); + } +}); diff --git a/server/src/hackathons/hackathon.service.js b/server/src/hackathons/hackathon.service.js new file mode 100644 index 00000000..e1da4a03 --- /dev/null +++ b/server/src/hackathons/hackathon.service.js @@ -0,0 +1,69 @@ +import { HackathonModel } from '../../schema/hackathon/hackathonSchema.js'; + +const getAllHackathons = async () => { + try { + const hackathon = await HackathonModel.find({}); + return hackathon; + } catch (error) { + throw new Error(error); + } +}; + +const getHackathonsById = async (_id) => { + try { + const hackathon = await HackathonModel.find({ _id }); + return hackathon; + } catch (error) { + throw new Error(error); + } +}; + +const getHackathonsBySlug = async (slug) => { + try { + const hackathon = await HackathonModel.find({ slug }); + return hackathon; + } catch (error) { + throw new Error(error); + } +}; + +const createHackathon = async (hackathonInfo) => { + try { + const hackathon = new HackathonModel(hackathonInfo); + await hackathon.save(); + return hackathon; + } catch (error) { + throw new Error(error); + } +}; +const updateHackathon = async (_id, updatedValue) => { + try { + const hackathon = await HackathonModel.findOneAndUpdate( + { _id: _id }, + { $set: updatedValue }, + { returnOriginal: false } + ); + + return hackathon; + } catch (error) { + throw new Error(error); + } +}; + +const deleteHackathon = async (_id) => { + try { + const hackathon = await HackathonModel.deleteOne({ _id: _id }); + return hackathon; + } catch (error) { + throw new Error(error); + } +}; + +export const HackathonService = { + getAllHackathons, + getHackathonsById, + getHackathonsBySlug, + createHackathon, + updateHackathon, + deleteHackathon, +}; diff --git a/server/src/users/user.router.js b/server/src/users/user.router.js new file mode 100644 index 00000000..67cb0d63 --- /dev/null +++ b/server/src/users/user.router.js @@ -0,0 +1,70 @@ +import { UserService } from './user.service.js'; +import express from 'express'; + +export const userRouter = express.Router(); + +//get user by id + +userRouter.get('/:id', async (req, res) => { + try { + const { id } = req.params; + if (!id) { + res.status(422).send({ success: false, message: 'Invalid id parameter' }); + } + const user = await UserService.getUser(id); + res.status(200).send({ success: true, user: user }); + } catch (error) { + res.status(500).json({ success: false, message: 'Internal server error' }); + } +}); + +//create user + +userRouter.post('/register', async (req, res) => { + try { + const { data } = req.body; + if (!data) { + res.status(422).send({ success: false, message: 'Invalid data' }); + } + const user = await UserService.createUser(data); + if (user === 'user exists') { + res.status(200).json({ message: 'User already exists' }); + } + res.status(200).send({ success: true, user: 'registration successful' }); + } catch (error) { + res.status(500).json({ success: false, message: 'Internal server error' }); + } +}); + +//login user + +userRouter.post('/login', async (req, res) => { + try { + const user = await UserService.loginUser(); + if (user === 404) { + res.status(404).json({ message: 'User not found' }); + } + if (user === 401) { + res.status(401).json({ message: 'Invalid Credentials' }); + } + res.status(200).send({ success: true, user: 'login successful' }); + } catch (error) { + res.status(500).json({ success: false, message: 'Internal server error' }); + } +}); + +//update user + +userRouter.post('/update/:id', async (req, res) => { + try { + const { id } = req.params; + + if (!id) { + res.status(422).send({ success: false, message: 'Invalid id parameter' }); + } + const user = await UserService.updateUser(id); + res.status(200).send({ success: true, user: user }); + } catch (error) { + res.status(500).json({ success: false, message: 'Internal server error' }); + } +}); diff --git a/server/src/users/user.service.js b/server/src/users/user.service.js new file mode 100644 index 00000000..74e998ec --- /dev/null +++ b/server/src/users/user.service.js @@ -0,0 +1,51 @@ +import { UserModel } from '../../schema/user/UserSchema.js'; + +const register = async (userInfo) => { + try { + // const { email, ...data } = userInfo + + const newUser = new UserModel(userInfo); + await newUser.save(); + return newUser; + } catch (error) { + throw new Error(error); + } +}; + +// eslint-disable-next-line unused-imports/no-unused-vars +const login = async () => { + try { + // const { email, password } = userInfo; + } catch (error) { + throw new Error(error); + } +}; + +const updateUser = async (_id, userInfo) => { + try { + const user = await UserModel.findOneAndUpdate( + { _id: _id }, + { $set: userInfo }, + { returnOriginal: false } + ); + return user; + } catch (error) { + throw new Error(error); + } +}; + +const getUser = async (_id) => { + try { + const user = await UserModel.findOne({ _id }); + return user; + } catch (error) { + throw new Error(error); + } +}; + +export const UserService = { + register, + login, + updateUser, + getUser, +}; diff --git a/src/pages/privacy.tsx b/src/pages/privacy.tsx index 3cfa3e5f..e5427736 100644 --- a/src/pages/privacy.tsx +++ b/src/pages/privacy.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +// import React from 'react'; export default function PrivacyPolicy() { return ( diff --git a/src/pages/terms.tsx b/src/pages/terms.tsx index 35f5f2f1..fe1cc8dc 100644 --- a/src/pages/terms.tsx +++ b/src/pages/terms.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +// import React from 'react'; export default function Terms() { return (