diff --git a/backend/controllers/auth.controller.js b/backend/controllers/auth.controller.js new file mode 100644 index 0000000..ea65de0 --- /dev/null +++ b/backend/controllers/auth.controller.js @@ -0,0 +1,87 @@ +import bcrypt from "bcryptjs"; +import User from "../models/user.model.js"; + +export const signup = async (req, res) => { + try { + const { name, email, password, mobileNo, role } = req.body; + + //Validators + if (password.length < 6) { + return res.status(400).json({ error: "Pasword should be atleast 6 characters long" }); + } + if (name.length < 2) { + return res.status(400).json({ error: "Name should be atleast 2 characters long" }); + } + if (mobileNo.length != 10) { + return res.status(400).json({ error: "Enter a valid Mobile No." }); + } + + const user = await User.findOne({ email }); + if (user) { + return res.status(400).json({ error: "User with this email already exists. Try logging into your account or signup with another email" }); + } + + const salt = await bcrypt.genSalt(10); + const hashedPassword = await bcrypt.hash(password, salt); + + const newUser = new User({ + name, + email, + password: hashedPassword, + mobileNo, + role, + }); + + if (newUser) { + await newUser.save(); + return res.status(201).json({ + _id: newUser._id, + name: newUser.name, + email: newUser.email, + mobileNo: newUser.mobileNo, + role: newUser.role + }); + } else { + return res.status(400).json({ error: "Invalid User Data" }); + } + + } catch (error) { + console.log("Error in Signup controller", error.message); + return res.status(500).json({ error: "Internal Server Error" }); + } +} + +export const login = async (req, res) => { + try { + const { email, password } = req.body; + const user = await User.findOne({ email }); + if (!user) { + return res.status(400).json({ error: "Cannot find User" }); + } + + const isPaswordCorrect = await bcrypt.compare(password, user.password || ""); + if (!isPaswordCorrect) { + return res.status(400).json({ error: "Invalid Login Credentials" }); + } + + res.status(200).json({ + _id: user._id, + name: user.name, + email: user.email, + mobileNo: user.mobileNo, + role: user.role + }); + } catch (error) { + console.log("Error in Login controller", error.message); + res.status(500).json({ error: "Internal Server Error" }); + } +} + +export const logout = (req, res) => { + try { + res.status(200).json({ message: "Logged out Successfully" }); + } catch (error) { + console.log("Error in Logout controller", error.message); + res.status(500).json({ error: "Internal Server Error" }); + } +} \ No newline at end of file diff --git a/backend/db/connectToMongoDB.js b/backend/db/connectToMongoDB.js new file mode 100644 index 0000000..8299ca3 --- /dev/null +++ b/backend/db/connectToMongoDB.js @@ -0,0 +1,12 @@ +import mongoose from "mongoose"; + +const connectToMongoDB = async () => { + try { + await mongoose.connect(process.env.MONGODB_URI); + console.log("Connected to MongoDB"); + } catch (error) { + console.log("Error in connecting to MongoDB"); + } +} + +export default connectToMongoDB; \ No newline at end of file diff --git a/backend/index.js b/backend/index.js index b54c8f3..1c73b9f 100644 --- a/backend/index.js +++ b/backend/index.js @@ -1,14 +1,47 @@ import express from "express"; import dotenv from "dotenv"; +import bodyParser from "body-parser"; +import morgan from "morgan"; +import helmet from "helmet"; +import cors from "cors"; dotenv.config(); +import connectToMongoDB from "./db/connectToMongoDB.js"; +import authRoutes from "./routes/auth.routes.js"; + const PORT = process.env.PORT || 5000; const app = express(); +const corsConfig = { + origin: "*", + methods: [ + 'GET', + 'POST', + 'PATCH', + 'DELETE' + ], + allowHeaders: [ + 'Content-Type' + ], + credentials: true +}; + +//middlewares +app.use(express.json()); +app.use(bodyParser.json()); +app.use(bodyParser.urlencoded({ extended: true })); +app.use(morgan("common")); +app.use(helmet()); +app.use(helmet.crossOriginResourcePolicy({ policy: "cross-origin" })); +app.use(cors(corsConfig)); + app.get("/api/v1", (req, res) => { res.send("

Test...All Up & Running!

"); }); +app.use("/api/v1/auth", authRoutes); + app.listen(PORT, () => { console.log(`Server Listening on Port ${PORT}`); + connectToMongoDB(); }); \ No newline at end of file diff --git a/backend/models/user.model.js b/backend/models/user.model.js new file mode 100644 index 0000000..63fb4f5 --- /dev/null +++ b/backend/models/user.model.js @@ -0,0 +1,32 @@ +import mongoose from "mongoose"; + +const userSchema = new mongoose.Schema({ + name: { + type: String, + min: 2, + required: true + }, + email: { + type: String, + required: true + }, + password: { + type: String, + min: 6, + required: true + }, + mobileNo: { + type: String, + max: 10, + min: 10, + required: true + }, + role: { + type: String, + enum: ["Coach", "Member", "Parent", "Administrator", "Participant"], + required: true + } +}, { timestamps: true }); + +const User = mongoose.model("User", userSchema); +export default User; \ No newline at end of file diff --git a/backend/package-lock.json b/backend/package-lock.json index eea05f4..e69d839 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -9,18 +9,41 @@ "version": "1.0.0", "license": "ISC", "dependencies": { + "bcryptjs": "^2.4.3", "body-parser": "^1.20.3", "cookie-parser": "^1.4.7", "cors": "^2.8.5", "dotenv": "^16.4.5", "express": "^4.21.1", "helmet": "^8.0.0", + "mongoose": "^8.8.1", "morgan": "^1.10.0" }, "devDependencies": { "nodemon": "^3.1.7" } }, + "node_modules/@mongodb-js/saslprep": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.9.tgz", + "integrity": "sha512-tVkljjeEaAhCqTzajSdgbQ6gE6f3oneVwa3iXR6csiEwXXOFsiC6Uh9iAjAhXPtqa/XMDHWjjeNH/77m/Yq2dw==", + "dependencies": { + "sparse-bitfield": "^3.0.3" + } + }, + "node_modules/@types/webidl-conversions": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", + "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==" + }, + "node_modules/@types/whatwg-url": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz", + "integrity": "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==", + "dependencies": { + "@types/webidl-conversions": "*" + } + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -73,6 +96,11 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, + "node_modules/bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==" + }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -130,6 +158,14 @@ "node": ">=8" } }, + "node_modules/bson": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-6.9.0.tgz", + "integrity": "sha512-X9hJeyeM0//Fus+0pc5dSUMhhrrmWwQUtdavaQeF3Ta6m69matZkGWV/MrBcnwUeLC8W9kwwc2hfkZgUuCX3Ig==", + "engines": { + "node": ">=16.20.1" + } + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -644,6 +680,14 @@ "node": ">=0.12.0" } }, + "node_modules/kareem": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz", + "integrity": "sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q==", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -652,6 +696,11 @@ "node": ">= 0.6" } }, + "node_modules/memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==" + }, "node_modules/merge-descriptors": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", @@ -710,6 +759,86 @@ "node": "*" } }, + "node_modules/mongodb": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.10.0.tgz", + "integrity": "sha512-gP9vduuYWb9ZkDM546M+MP2qKVk5ZG2wPF63OvSRuUbqCR+11ZCAE1mOfllhlAG0wcoJY5yDL/rV3OmYEwXIzg==", + "dependencies": { + "@mongodb-js/saslprep": "^1.1.5", + "bson": "^6.7.0", + "mongodb-connection-string-url": "^3.0.0" + }, + "engines": { + "node": ">=16.20.1" + }, + "peerDependencies": { + "@aws-sdk/credential-providers": "^3.188.0", + "@mongodb-js/zstd": "^1.1.0", + "gcp-metadata": "^5.2.0", + "kerberos": "^2.0.1", + "mongodb-client-encryption": ">=6.0.0 <7", + "snappy": "^7.2.2", + "socks": "^2.7.1" + }, + "peerDependenciesMeta": { + "@aws-sdk/credential-providers": { + "optional": true + }, + "@mongodb-js/zstd": { + "optional": true + }, + "gcp-metadata": { + "optional": true + }, + "kerberos": { + "optional": true + }, + "mongodb-client-encryption": { + "optional": true + }, + "snappy": { + "optional": true + }, + "socks": { + "optional": true + } + } + }, + "node_modules/mongodb-connection-string-url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.1.tgz", + "integrity": "sha512-XqMGwRX0Lgn05TDB4PyG2h2kKO/FfWJyCzYQbIhXUxz7ETt0I/FqHjUeqj37irJ+Dl1ZtU82uYyj14u2XsZKfg==", + "dependencies": { + "@types/whatwg-url": "^11.0.2", + "whatwg-url": "^13.0.0" + } + }, + "node_modules/mongoose": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.8.1.tgz", + "integrity": "sha512-l7DgeY1szT98+EKU8GYnga5WnyatAu+kOQ2VlVX1Mxif6A0Umt0YkSiksCiyGxzx8SPhGe9a53ND1GD4yVDrPA==", + "dependencies": { + "bson": "^6.7.0", + "kareem": "2.6.3", + "mongodb": "~6.10.0", + "mpath": "0.9.0", + "mquery": "5.0.0", + "ms": "2.1.3", + "sift": "17.1.3" + }, + "engines": { + "node": ">=16.20.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mongoose" + } + }, + "node_modules/mongoose/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, "node_modules/morgan": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", @@ -736,6 +865,46 @@ "node": ">= 0.8" } }, + "node_modules/mpath": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", + "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mquery": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", + "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", + "dependencies": { + "debug": "4.x" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/mquery/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/mquery/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -890,6 +1059,14 @@ "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", "dev": true }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "engines": { + "node": ">=6" + } + }, "node_modules/qs": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", @@ -1062,6 +1239,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/sift": { + "version": "17.1.3", + "resolved": "https://registry.npmjs.org/sift/-/sift-17.1.3.tgz", + "integrity": "sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ==" + }, "node_modules/simple-update-notifier": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", @@ -1074,6 +1256,14 @@ "node": ">=10" } }, + "node_modules/sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "dependencies": { + "memory-pager": "^1.0.2" + } + }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -1123,6 +1313,17 @@ "nodetouch": "bin/nodetouch.js" } }, + "node_modules/tr46": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", + "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", + "dependencies": { + "punycode": "^2.3.0" + }, + "engines": { + "node": ">=14" + } + }, "node_modules/type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -1164,6 +1365,26 @@ "engines": { "node": ">= 0.8" } + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-13.0.0.tgz", + "integrity": "sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==", + "dependencies": { + "tr46": "^4.1.1", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=16" + } } } } diff --git a/backend/package.json b/backend/package.json index bc94acc..cd0690a 100644 --- a/backend/package.json +++ b/backend/package.json @@ -11,12 +11,14 @@ "author": "", "license": "ISC", "dependencies": { + "bcryptjs": "^2.4.3", "body-parser": "^1.20.3", "cookie-parser": "^1.4.7", "cors": "^2.8.5", "dotenv": "^16.4.5", "express": "^4.21.1", "helmet": "^8.0.0", + "mongoose": "^8.8.1", "morgan": "^1.10.0" }, "devDependencies": { diff --git a/backend/routes/auth.routes.js b/backend/routes/auth.routes.js new file mode 100644 index 0000000..2920b12 --- /dev/null +++ b/backend/routes/auth.routes.js @@ -0,0 +1,10 @@ +import express from "express"; +import { login, logout, signup } from "../controllers/auth.controller.js"; + +const router = express.Router(); + +router.post("/signup", signup); +router.post("/login", login); +router.post("/logout", logout); + +export default router; \ No newline at end of file