diff --git a/BackEnd/index.js b/BackEnd/index.js index ed38e59..b9d93d5 100644 --- a/BackEnd/index.js +++ b/BackEnd/index.js @@ -22,6 +22,12 @@ import blogRoutes from './routes/blogRoutes.js'; import cropRoutes from './routes/cropRoutes.js'; import diseaseRoutes from './routes/diseaseRoutes.js'; +import passport from 'passport'; +import session from 'express-session'; +import MongoStore from 'connect-mongo'; +import User from './models/userModel.js'; +import './passport-setup.js'; + if (process.env.NODE_ENV !== 'production') { dotenv.config({ path: findConfig('.env.dev') }); } @@ -53,6 +59,73 @@ const csrfProtection = csurf({ }, }); +const store = MongoStore.create({ + mongoUrl: process.env.MONGO_URI, + collectionName: "sessions", +}); + +app.use( + session({ + secret: process.env.COOKIE_KEY, + saveUninitialized: false, + resave: false, + store: store, + cookie: { secure: process.env.NODE_ENV === "production" }, + }) +); + +app.use(passport.initialize()); +app.use(passport.session()); + + +app.get( + "/auth/google", + passport.authenticate("google", { + scope: ["profile", "email"], + }) +); + +app.get( + "/auth/google/callback", + passport.authenticate("google", { + failureRedirect: `${process.env.FRONTEND_URL}/login`, + }), + async (req, res) => { + const { googleId, username, email, firstName, lastName, profilePic } = + req.user; + console.log("user", req.user); + + let existingUser = await User.findOne({ googleId: googleId }); + console.log("existingUser", existingUser); + + if (!existingUser) { + existingUser = new User({ + username: username, + googleId: googleId, + email: email, + firstName: firstName, + lastName: lastName, + profilePic: profilePic || User.schema.path("profilePic").defaultValue, + }); + await existingUser.save(); + } + + const googleAccessToken = req.user.accessToken; + + req.login(existingUser, (err) => { + if (err) return res.status(500).send(err); + + res.redirect( + `${process.env.FRONTEND_URL}/login?googleAuthSuccess` + + `&username=${username}&email=${email}&firstName=${firstName}` + + `&lastName=${lastName}&profilePic=${profilePic}` + + `&role=${existingUser.role}&request=${existingUser.request}` + + `&token=${googleAccessToken}` + ); + }); + } +); + // Use middleware to increment visitor count app.use(visitMiddleware); app.use(incrementCountMiddleware); diff --git a/BackEnd/models/userModel.js b/BackEnd/models/userModel.js index 585de5e..3b97e70 100644 --- a/BackEnd/models/userModel.js +++ b/BackEnd/models/userModel.js @@ -33,6 +33,10 @@ const userSchema = mongoose.Schema( default: 'https://images.unsplash.com/photo-1633332755192-727a05c4013d?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=580&q=80', }, + googleId: { + type: String, + unique: true, + }, role: { type: String, enum: ['regular', 'contributor', 'moderator', 'admin'], diff --git a/BackEnd/package-lock.json b/BackEnd/package-lock.json index fddbe96..600a50c 100644 --- a/BackEnd/package-lock.json +++ b/BackEnd/package-lock.json @@ -14,7 +14,9 @@ "babel-jest": "^29.5.0", "bcryptjs": "^2.4.3", "colors": "^1.4.0", + "connect-mongo": "^5.1.0", "cookie-parser": "^1.4.6", + "cookie-session": "^2.1.0", "cors": "^2.8.5", "csurf": "^1.11.0", "dotenv": "^16.0.3", @@ -26,7 +28,9 @@ "helmet": "^7.1.0", "jsonwebtoken": "^9.0.2", "mongoose": "^8.0.0", - "nodemon": "^3.0.0" + "nodemon": "^3.0.0", + "passport": "^0.7.0", + "passport-google-oauth20": "^2.0.0" }, "devDependencies": { "jest": "^29.5.0", @@ -2448,6 +2452,17 @@ "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", "dev": true }, + "node_modules/asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + } + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -2593,6 +2608,14 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "node_modules/base64url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", + "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/bcryptjs": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", @@ -2606,6 +2629,11 @@ "node": ">=8" } }, + "node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, "node_modules/body-parser": { "version": "1.20.3", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", @@ -2941,6 +2969,43 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, + "node_modules/connect-mongo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/connect-mongo/-/connect-mongo-5.1.0.tgz", + "integrity": "sha512-xT0vxQLqyqoUTxPLzlP9a/u+vir0zNkhiy9uAdHjSCcUUf7TS5b55Icw8lVyYFxfemP3Mf9gdwUOgeF3cxCAhw==", + "dependencies": { + "debug": "^4.3.1", + "kruptein": "^3.0.0" + }, + "engines": { + "node": ">=12.9.0" + }, + "peerDependencies": { + "express-session": "^1.17.1", + "mongodb": ">= 5.1.0 < 7" + } + }, + "node_modules/connect-mongo/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/connect-mongo/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/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -2995,6 +3060,33 @@ "node": ">= 0.6" } }, + "node_modules/cookie-session": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cookie-session/-/cookie-session-2.1.0.tgz", + "integrity": "sha512-u73BDmR8QLGcs+Lprs0cfbcAPKl2HnPcjpwRXT41sEV4DRJ2+W0vJEEZkG31ofkx+HZflA70siRIjiTdIodmOQ==", + "dependencies": { + "cookies": "0.9.1", + "debug": "3.2.7", + "on-headers": "~1.0.2", + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/cookie-session/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/cookie-session/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/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", @@ -3006,6 +3098,18 @@ "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", "dev": true }, + "node_modules/cookies": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.9.1.tgz", + "integrity": "sha512-TG2hpqe4ELx54QER/S3HQ9SRVnQnGBtKUz5bLQWtYAQ+o6GpgMs6sYUvaiJjVxb+UXwhRhAEP3m7LbsIZ77Hmw==", + "dependencies": { + "depd": "~2.0.0", + "keygrip": "~1.1.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/core-js-compat": { "version": "3.38.1", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.1.tgz", @@ -4813,6 +4917,17 @@ "node": ">=12.0.0" } }, + "node_modules/keygrip": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz", + "integrity": "sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==", + "dependencies": { + "tsscmp": "1.0.6" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -4822,6 +4937,17 @@ "node": ">=6" } }, + "node_modules/kruptein": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/kruptein/-/kruptein-3.0.7.tgz", + "integrity": "sha512-vTftnEjfbqFHLqxDUMQCj6gBo5lKqjV4f0JsM8rk8rM3xmvFZ2eSy4YALdaye7E+cDKnEj7eAjFR3vwh8a4PgQ==", + "dependencies": { + "asn1.js": "^5.4.1" + }, + "engines": { + "node": ">8" + } + }, "node_modules/leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -5017,6 +5143,11 @@ "node": ">=6" } }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -5256,6 +5387,11 @@ "node": ">=8" } }, + "node_modules/oauth": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.10.0.tgz", + "integrity": "sha512-1orQ9MT1vHFGQxhuy7E/0gECD3fd2fCC+PIX+/jgmU/gI3EpRocXtmtvxCO5x3WZ443FLTLFWNDjl5MPJf9u+Q==" + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -5400,6 +5536,61 @@ "node": ">= 0.8" } }, + "node_modules/passport": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.7.0.tgz", + "integrity": "sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ==", + "dependencies": { + "passport-strategy": "1.x.x", + "pause": "0.0.1", + "utils-merge": "^1.0.1" + }, + "engines": { + "node": ">= 0.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jaredhanson" + } + }, + "node_modules/passport-google-oauth20": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/passport-google-oauth20/-/passport-google-oauth20-2.0.0.tgz", + "integrity": "sha512-KSk6IJ15RoxuGq7D1UKK/8qKhNfzbLeLrG3gkLZ7p4A6DBCcv7xpyQwuXtWdpyR0+E0mwkpjY1VfPOhxQrKzdQ==", + "dependencies": { + "passport-oauth2": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/passport-oauth2": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.8.0.tgz", + "integrity": "sha512-cjsQbOrXIDE4P8nNb3FQRCCmJJ/utnFKEz2NX209f7KOHPoX18gF7gBzBbLLsj2/je4KrgiwLLGjf0lm9rtTBA==", + "dependencies": { + "base64url": "3.x.x", + "oauth": "0.10.x", + "passport-strategy": "1.x.x", + "uid2": "0.0.x", + "utils-merge": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jaredhanson" + } + }, + "node_modules/passport-strategy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", + "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==", + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -5436,6 +5627,11 @@ "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", "license": "MIT" }, + "node_modules/pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" + }, "node_modules/picocolors": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", @@ -6271,6 +6467,11 @@ "node": ">= 0.8" } }, + "node_modules/uid2": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.4.tgz", + "integrity": "sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA==" + }, "node_modules/undefsafe": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", @@ -8185,6 +8386,17 @@ "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", "dev": true }, + "asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + } + }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -8295,6 +8507,11 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "base64url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", + "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==" + }, "bcryptjs": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", @@ -8305,6 +8522,11 @@ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" }, + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, "body-parser": { "version": "1.20.3", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", @@ -8526,6 +8748,30 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, + "connect-mongo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/connect-mongo/-/connect-mongo-5.1.0.tgz", + "integrity": "sha512-xT0vxQLqyqoUTxPLzlP9a/u+vir0zNkhiy9uAdHjSCcUUf7TS5b55Icw8lVyYFxfemP3Mf9gdwUOgeF3cxCAhw==", + "requires": { + "debug": "^4.3.1", + "kruptein": "^3.0.0" + }, + "dependencies": { + "debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "requires": { + "ms": "^2.1.3" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, "content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -8565,6 +8811,32 @@ } } }, + "cookie-session": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cookie-session/-/cookie-session-2.1.0.tgz", + "integrity": "sha512-u73BDmR8QLGcs+Lprs0cfbcAPKl2HnPcjpwRXT41sEV4DRJ2+W0vJEEZkG31ofkx+HZflA70siRIjiTdIodmOQ==", + "requires": { + "cookies": "0.9.1", + "debug": "3.2.7", + "on-headers": "~1.0.2", + "safe-buffer": "5.2.1" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, "cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", @@ -8576,6 +8848,15 @@ "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", "dev": true }, + "cookies": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.9.1.tgz", + "integrity": "sha512-TG2hpqe4ELx54QER/S3HQ9SRVnQnGBtKUz5bLQWtYAQ+o6GpgMs6sYUvaiJjVxb+UXwhRhAEP3m7LbsIZ77Hmw==", + "requires": { + "depd": "~2.0.0", + "keygrip": "~1.1.0" + } + }, "core-js-compat": { "version": "3.38.1", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.1.tgz", @@ -9908,12 +10189,28 @@ "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.5.1.tgz", "integrity": "sha512-7jFxRVm+jD+rkq3kY0iZDJfsO2/t4BBPeEb2qKn2lR/9KhuksYk5hxzfRYWMPV8P/x2d0kHD306YyWLzjjH+uA==" }, + "keygrip": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz", + "integrity": "sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==", + "requires": { + "tsscmp": "1.0.6" + } + }, "kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", "dev": true }, + "kruptein": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/kruptein/-/kruptein-3.0.7.tgz", + "integrity": "sha512-vTftnEjfbqFHLqxDUMQCj6gBo5lKqjV4f0JsM8rk8rM3xmvFZ2eSy4YALdaye7E+cDKnEj7eAjFR3vwh8a4PgQ==", + "requires": { + "asn1.js": "^5.4.1" + } + }, "leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -10057,6 +10354,11 @@ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, "minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -10213,6 +10515,11 @@ "path-key": "^3.0.0" } }, + "oauth": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.10.0.tgz", + "integrity": "sha512-1orQ9MT1vHFGQxhuy7E/0gECD3fd2fCC+PIX+/jgmU/gI3EpRocXtmtvxCO5x3WZ443FLTLFWNDjl5MPJf9u+Q==" + }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -10307,6 +10614,41 @@ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" }, + "passport": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.7.0.tgz", + "integrity": "sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ==", + "requires": { + "passport-strategy": "1.x.x", + "pause": "0.0.1", + "utils-merge": "^1.0.1" + } + }, + "passport-google-oauth20": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/passport-google-oauth20/-/passport-google-oauth20-2.0.0.tgz", + "integrity": "sha512-KSk6IJ15RoxuGq7D1UKK/8qKhNfzbLeLrG3gkLZ7p4A6DBCcv7xpyQwuXtWdpyR0+E0mwkpjY1VfPOhxQrKzdQ==", + "requires": { + "passport-oauth2": "1.x.x" + } + }, + "passport-oauth2": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.8.0.tgz", + "integrity": "sha512-cjsQbOrXIDE4P8nNb3FQRCCmJJ/utnFKEz2NX209f7KOHPoX18gF7gBzBbLLsj2/je4KrgiwLLGjf0lm9rtTBA==", + "requires": { + "base64url": "3.x.x", + "oauth": "0.10.x", + "passport-strategy": "1.x.x", + "uid2": "0.0.x", + "utils-merge": "1.x.x" + } + }, + "passport-strategy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", + "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==" + }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -10333,6 +10675,11 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==" }, + "pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" + }, "picocolors": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", @@ -10920,6 +11267,11 @@ "random-bytes": "~1.0.0" } }, + "uid2": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.4.tgz", + "integrity": "sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA==" + }, "undefsafe": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", diff --git a/BackEnd/package.json b/BackEnd/package.json index dd1c225..18389ee 100644 --- a/BackEnd/package.json +++ b/BackEnd/package.json @@ -16,7 +16,9 @@ "babel-jest": "^29.5.0", "bcryptjs": "^2.4.3", "colors": "^1.4.0", + "connect-mongo": "^5.1.0", "cookie-parser": "^1.4.6", + "cookie-session": "^2.1.0", "cors": "^2.8.5", "csurf": "^1.11.0", "dotenv": "^16.0.3", @@ -28,7 +30,9 @@ "helmet": "^7.1.0", "jsonwebtoken": "^9.0.2", "mongoose": "^8.0.0", - "nodemon": "^3.0.0" + "nodemon": "^3.0.0", + "passport": "^0.7.0", + "passport-google-oauth20": "^2.0.0" }, "devDependencies": { "jest": "^29.5.0", diff --git a/BackEnd/passport-setup.js b/BackEnd/passport-setup.js new file mode 100644 index 0000000..0d2cd05 --- /dev/null +++ b/BackEnd/passport-setup.js @@ -0,0 +1,51 @@ +import passport from "passport"; +import GoogleStrategy from "passport-google-oauth20"; +import User from "./models/userModel.js"; +import dotenv from "dotenv"; +import findConfig from "find-config"; + +if (process.env.NODE_ENV !== "production") { + dotenv.config({ path: findConfig(".env.dev") }); +} + +passport.serializeUser((user, done) => { + done(null, user.id); +}); + +passport.deserializeUser((id, done) => { + User.findById(id).then((user) => { + done(null, user); + }); +}); + +passport.use( + new GoogleStrategy( + { + clientID: process.env.GOOGLE_CLIENT_ID, + clientSecret: process.env.GOOGLE_CLIENT_SECRET, + callbackURL: "/auth/google/callback", + }, + (accessToken, refreshToken, profile, done) => { + User.findOne({ googleId: profile.id }).then((existingUser) => { + if (existingUser) { + existingUser.accessToken = accessToken; + done(null, existingUser); + } else { + const newUser = new User({ + username: profile.name.givenName + profile.name.familyName, + googleId: profile.id, + email: profile.emails[0].value, + firstName: profile.name.givenName, + lastName: profile.name.familyName, + profilePic: profile._json.picture, + }); + + newUser.save().then((user) => { + user.accessToken = accessToken; + done(null, user); + }); + } + }); + } + ) +); diff --git a/FrontEnd/src/assets/googleLogo.svg b/FrontEnd/src/assets/googleLogo.svg new file mode 100644 index 0000000..088288f --- /dev/null +++ b/FrontEnd/src/assets/googleLogo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/FrontEnd/src/assets/logo.svg b/FrontEnd/src/assets/logo.svg new file mode 100644 index 0000000..93d6402 --- /dev/null +++ b/FrontEnd/src/assets/logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/FrontEnd/src/assets/logoLeaf.svg b/FrontEnd/src/assets/logoLeaf.svg new file mode 100644 index 0000000..48fe1d9 --- /dev/null +++ b/FrontEnd/src/assets/logoLeaf.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/FrontEnd/src/assets/react.svg b/FrontEnd/src/assets/react.svg deleted file mode 100644 index 6c87de9..0000000 --- a/FrontEnd/src/assets/react.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/FrontEnd/src/components/common/Footer.jsx b/FrontEnd/src/components/common/Footer.jsx index da69834..deaaffa 100644 --- a/FrontEnd/src/components/common/Footer.jsx +++ b/FrontEnd/src/components/common/Footer.jsx @@ -1,6 +1,6 @@ import { Link } from 'react-router-dom'; import { FaFacebookF, FaInstagram, FaTwitter, FaYoutube } from 'react-icons/fa'; -import { ImLeaf } from 'react-icons/im'; +import logoLeaf from '../../assets/logoLeaf.svg'; const Footer = () => { return ( @@ -8,7 +8,7 @@ const Footer = () => {
- + logo AgroHelp diff --git a/FrontEnd/src/components/common/Navbar.jsx b/FrontEnd/src/components/common/Navbar.jsx index 58d20a2..3451d78 100644 --- a/FrontEnd/src/components/common/Navbar.jsx +++ b/FrontEnd/src/components/common/Navbar.jsx @@ -13,7 +13,7 @@ import { FaLock, FaPen, } from 'react-icons/fa'; -import { ImLeaf } from 'react-icons/im'; +import logoLeaf from '../../assets/logoLeaf.svg'; import { HiMenu, HiOutlineX } from 'react-icons/hi'; import { useGlobalContext } from '../../context/ContextProvider'; import { logout } from '../../api/user'; @@ -100,7 +100,7 @@ const Navbar = () => {
- + logo AgroHelp diff --git a/FrontEnd/src/pages/common/Login.jsx b/FrontEnd/src/pages/common/Login.jsx index 0dce1de..5436819 100644 --- a/FrontEnd/src/pages/common/Login.jsx +++ b/FrontEnd/src/pages/common/Login.jsx @@ -1,16 +1,23 @@ -import React from 'react'; import { useState, useEffect } from 'react'; import { Link, useNavigate, useLocation } from 'react-router-dom'; import { useGlobalContext } from '../../context/ContextProvider'; import { login } from '../../api/user'; -import { ImLeaf } from 'react-icons/im'; +import logo from '../../assets/logo.svg'; +import googleLogo from '../../assets/googleLogo.svg'; +import { IoIosEyeOff, IoIosEye } from 'react-icons/io'; const Login = () => { + const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); + const [showPassword, setShowPassword] = useState(false); + + const togglePasswordVisibility = () => { + setShowPassword(!showPassword); + }; const { setUser } = useGlobalContext(); - const { error, user } = useGlobalContext(); + const { user } = useGlobalContext(); const navigate = useNavigate(); const location = useLocation(); @@ -21,7 +28,30 @@ const Login = () => { if (user) { navigate(redirect); } - }, [navigate, user, redirect]); + const params = new URLSearchParams(location.search); + const token = params.get('token'); + const username = params.get('username'); + const email = params.get('email'); + const firstName = params.get('firstName'); + const lastName = params.get('lastName'); + const profilePic = params.get('profilePic'); + + if (token) { + const userData = { + token, + username, + email, + firstName, + lastName, + profilePic, + }; + + localStorage.setItem('userInfo', JSON.stringify(userData)); + setUser(userData); + + navigate('/home'); + } + }, [user, location, redirect, navigate, setUser]); const submitHandler = async (e) => { e.preventDefault(); @@ -30,356 +60,82 @@ const Login = () => { const { data } = await login(email, password); if (data) { setUser(data); + localStorage.setItem('userInfo', JSON.stringify(data)); + navigate(redirect); } } }; - return ( -
-