From 3f6d52736b45be51baba471ddcf3bd2d711308d7 Mon Sep 17 00:00:00 2001 From: Mohamed Soliman <123838217+mel3assal@users.noreply.github.com> Date: Wed, 18 Sep 2024 20:44:35 +0300 Subject: [PATCH] facebook login added --- database/models/userModel.ts | 2 + dist/database/models/userModel.js | 2 + dist/index.js | 15 ++ dist/src/bootstrab.js | 5 + dist/src/middleware/validate.js | 7 +- dist/src/modules/user/socialNetworkLogin.js | 53 +++++ dist/src/modules/user/user.validation.js | 4 +- index.ts | 22 +- package-lock.json | 217 ++++++++++++++++++-- package.json | 7 +- src/bootstrab.ts | 2 + src/middleware/validate.ts | 17 +- src/modules/user/socialNetworkLogin.ts | 53 +++++ src/modules/user/user.controller.ts | 1 - src/modules/user/user.validation.ts | 4 +- 15 files changed, 381 insertions(+), 30 deletions(-) create mode 100644 dist/src/modules/user/socialNetworkLogin.js create mode 100644 src/modules/user/socialNetworkLogin.ts diff --git a/database/models/userModel.ts b/database/models/userModel.ts index 4e6bb2d..eedc469 100644 --- a/database/models/userModel.ts +++ b/database/models/userModel.ts @@ -14,6 +14,8 @@ const userSchema = new Schema({ type: Boolean, default: false, }, + accountId:String, + provider:String }); userSchema.post("find", function (doc) { let url = process.env.BASE_URL+"/user"; diff --git a/dist/database/models/userModel.js b/dist/database/models/userModel.js index e7d68c0..1985fa2 100644 --- a/dist/database/models/userModel.js +++ b/dist/database/models/userModel.js @@ -16,6 +16,8 @@ const userSchema = new mongoose_1.Schema({ type: Boolean, default: false, }, + accountId: String, + provider: String }); userSchema.post("find", function (doc) { let url = process.env.BASE_URL + "/user"; diff --git a/dist/index.js b/dist/index.js index 4648711..23ed8d0 100644 --- a/dist/index.js +++ b/dist/index.js @@ -6,7 +6,9 @@ Object.defineProperty(exports, "__esModule", { value: true }); const express_1 = __importDefault(require("express")); const dbConn_1 = require("./database/dbConn"); const bootstrab_1 = require("./src/bootstrab"); +const express_session_1 = __importDefault(require("express-session")); require("dotenv/config"); +const passport_1 = __importDefault(require("passport")); const app = (0, express_1.default)(); const port = 3000; (0, dbConn_1.dbConn)(); @@ -14,3 +16,16 @@ app.use(express_1.default.json()); app.use('/uploads', express_1.default.static('src/uploads')); (0, bootstrab_1.bootstrab)(app); app.listen(port, () => console.log(`Example app listening on port ${port}!`)); +app.use((0, express_session_1.default)({ + resave: false, + saveUninitialized: true, + secret: 'MohamedElassal', +})); +app.use(passport_1.default.initialize()); +app.use(passport_1.default.session()); +passport_1.default.serializeUser(function (user, cb) { + cb(null, user); +}); +passport_1.default.deserializeUser(function (obj, cb) { + cb(null, obj); +}); diff --git a/dist/src/bootstrab.js b/dist/src/bootstrab.js index c5a33b7..92bca1d 100644 --- a/dist/src/bootstrab.js +++ b/dist/src/bootstrab.js @@ -1,4 +1,7 @@ "use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; Object.defineProperty(exports, "__esModule", { value: true }); exports.bootstrab = void 0; const user_routes_1 = require("./modules/user/user.routes"); @@ -6,11 +9,13 @@ const globalHandeling_1 = require("./middleware/errorHandeling/globalHandeling") const post_routes_1 = require("./modules/post/post.routes"); const comments_routes_1 = require("./modules/comment/comments.routes"); const reply_routes_1 = require("./modules/replie/reply.routes"); +const socialNetworkLogin_1 = __importDefault(require("./modules/user/socialNetworkLogin")); const bootstrab = function (app) { app.use('/users', user_routes_1.userRouter); app.use('/posts', post_routes_1.postRouter); app.use('/comments', comments_routes_1.commentRouter); app.use('/replies', reply_routes_1.replyRouter); + app.use(socialNetworkLogin_1.default); app.use(globalHandeling_1.globalHandeling); }; exports.bootstrab = bootstrab; diff --git a/dist/src/middleware/validate.js b/dist/src/middleware/validate.js index 0f71495..0a013d8 100644 --- a/dist/src/middleware/validate.js +++ b/dist/src/middleware/validate.js @@ -3,7 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true }); const appError_1 = require("../utils/appError"); const validate = (schema) => { return (req, res, next) => { - let files = () => { return { [`${req.file?.fieldname}`]: req.file }; }; + let files = () => { + if (!req.file) + return {}; + return { [`${req.file?.fieldname}`]: req.file }; + }; + console.log(req.query); const { error } = schema.validate({ ...req.body, ...req.params, diff --git a/dist/src/modules/user/socialNetworkLogin.js b/dist/src/modules/user/socialNetworkLogin.js new file mode 100644 index 0000000..140e73c --- /dev/null +++ b/dist/src/modules/user/socialNetworkLogin.js @@ -0,0 +1,53 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const passport_1 = __importDefault(require("passport")); +const userModel_1 = require("../../../database/models/userModel"); +const passport_facebook_1 = __importDefault(require("passport-facebook")); +const express_1 = require("express"); +const FacebookStrategy = passport_facebook_1.default.Strategy; +const facebookRouter = (0, express_1.Router)(); +require("dotenv/config"); +const appError_1 = require("../../utils/appError"); +const catchErrors_1 = require("../../middleware/errorHandeling/catchErrors"); +passport_1.default.use(new FacebookStrategy({ + clientID: '894388332019012', + clientSecret: 'f3ec0038f9c5e5bff630f117bcf799c5', + callbackURL: 'http://localhost:3000/', +}, async function (profile, cb) { + const user = await userModel_1.User.findOne({ + accountId: profile.id, + provider: 'facebook', + }); + if (!user) { + console.log('Adding new facebook user to DB..'); + const user = new userModel_1.User({ + accountId: profile.id, + name: profile.displayName, + provider: profile.provider, + }); + await user.save(); + // console.log(user); + return cb(null, profile); + } + else { + console.log('Facebook User already exist in DB..'); + // console.log(profile); + return cb(null, profile); + } +})); +facebookRouter.get('/facebook', (0, catchErrors_1.catchError)((req, res, next) => { + passport_1.default.authenticate('facebook', (err, user) => { + const userInfo = { + id: req.session.passport.user.id, + displayName: req.session.passport.user.displayName, + provider: req.session.passport.user.provider, + }; + if (err) + return next(new appError_1.AppError('login failed ', 401)); + res.json({ message: userInfo }); + }); +})); +exports.default = facebookRouter; diff --git a/dist/src/modules/user/user.validation.js b/dist/src/modules/user/user.validation.js index 257078f..44f7c3a 100644 --- a/dist/src/modules/user/user.validation.js +++ b/dist/src/modules/user/user.validation.js @@ -8,7 +8,7 @@ const joi_1 = __importDefault(require("joi")); const signupVal = joi_1.default.object({ name: joi_1.default.string().min(5).max(30).required(), email: joi_1.default.string().email().required(), - passowrd: joi_1.default.string().pattern(/^[A-Z][a-zA-Z0-9]{8,40}$/).required(), + password: joi_1.default.string().required(), rePassword: joi_1.default.valid(joi_1.default.ref('passowrd')).required(), bio: joi_1.default.string(), preferences: joi_1.default.string(), @@ -26,7 +26,7 @@ const signupVal = joi_1.default.object({ exports.signupVal = signupVal; const signInVal = joi_1.default.object({ email: joi_1.default.string().email().required(), - passowrd: joi_1.default.string().pattern(/^[A-Z][a-zA-Z0-9]{8,40}$/).required() + password: joi_1.default.string().required() }); exports.signInVal = signInVal; const updateProfileVal = joi_1.default.object({ diff --git a/index.ts b/index.ts index 4db5f84..17708fd 100644 --- a/index.ts +++ b/index.ts @@ -1,8 +1,9 @@ import express from 'express' import { dbConn } from './database/dbConn' import { bootstrab } from './src/bootstrab' -import fs from "fs" +import session from 'express-session' import 'dotenv/config' +import passport from 'passport' const app = express() const port = 3000 dbConn() @@ -10,3 +11,22 @@ app.use(express.json()) app.use('/uploads', express.static('src/uploads')); bootstrab(app) app.listen(port, () => console.log(`Example app listening on port ${port}!`)) + +app.use( + session({ + resave: false, + saveUninitialized: true, + secret: 'MohamedElassal', + }) + ); + + app.use(passport.initialize()); + app.use(passport.session()); + + passport.serializeUser(function (user, cb) { + cb(null, user); + }); + passport.deserializeUser(function (obj:object, cb) { + cb(null, obj); + }); + \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 70c199b..478ef92 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,22 +9,27 @@ "version": "1.0.0", "license": "ISC", "dependencies": { + "@types/express-session": "^1.18.0", "@types/jsonwebtoken": "^9.0.6", "@types/uuid": "^10.0.0", "bcrypt": "^5.1.1", "dotenv": "^16.4.5", "express": "^4.19.2", + "express-session": "^1.18.0", "joi": "^17.13.3", "jsonwebtoken": "^9.0.2", "mongoose": "^8.6.1", "multer": "^1.4.5-lts.1", + "passport": "^0.7.0", + "passport-facebook": "^3.0.0", "uuid": "^10.0.0" }, "devDependencies": { "@types/bcrypt": "^5.0.2", "@types/express": "^4.17.21", "@types/multer": "^1.4.12", - "@types/node": "^22.5.4" + "@types/node": "^22.5.4", + "@types/passport-facebook": "^3.0.3" } }, "node_modules/@hapi/hoek": { @@ -98,7 +103,6 @@ "version": "1.19.5", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", - "dev": true, "dependencies": { "@types/connect": "*", "@types/node": "*" @@ -108,7 +112,6 @@ "version": "3.4.38", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -117,7 +120,6 @@ "version": "4.17.21", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", - "dev": true, "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^4.17.33", @@ -129,7 +131,6 @@ "version": "4.19.5", "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.5.tgz", "integrity": "sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg==", - "dev": true, "dependencies": { "@types/node": "*", "@types/qs": "*", @@ -137,11 +138,19 @@ "@types/send": "*" } }, + "node_modules/@types/express-session": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/@types/express-session/-/express-session-1.18.0.tgz", + "integrity": "sha512-27JdDRgor6PoYlURY+Y5kCakqp5ulC0kmf7y+QwaY+hv9jEFuQOThgkjyA53RP3jmKuBsH5GR6qEfFmvb8mwOA==", + "license": "MIT", + "dependencies": { + "@types/express": "*" + } + }, "node_modules/@types/http-errors": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", - "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", - "dev": true + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==" }, "node_modules/@types/jsonwebtoken": { "version": "9.0.6", @@ -154,8 +163,7 @@ "node_modules/@types/mime": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", - "dev": true + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==" }, "node_modules/@types/multer": { "version": "1.4.12", @@ -174,23 +182,64 @@ "undici-types": "~6.19.2" } }, + "node_modules/@types/oauth": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/@types/oauth/-/oauth-0.9.5.tgz", + "integrity": "sha512-+oQ3C2Zx6ambINOcdIARF5Z3Tu3x//HipE889/fqo3sgpQZbe9c6ExdQFtN6qlhpR7p83lTZfPJt0tCAW29dog==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/passport": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.16.tgz", + "integrity": "sha512-FD0qD5hbPWQzaM0wHUnJ/T0BBCJBxCeemtnCwc/ThhTg3x9jfrAcRUmj5Dopza+MfFS9acTe3wk7rcVnRIp/0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/passport-facebook": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/passport-facebook/-/passport-facebook-3.0.3.tgz", + "integrity": "sha512-4cwyK2bGMo4Di8eMMLjf9JgDbpptRVYmStuy0ETZSaVo6fcY9+BtB9hCUmLEobUtqNHoIoXIWOCdDA2UynCUyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*", + "@types/passport": "*", + "@types/passport-oauth2": "*" + } + }, + "node_modules/@types/passport-oauth2": { + "version": "1.4.17", + "resolved": "https://registry.npmjs.org/@types/passport-oauth2/-/passport-oauth2-1.4.17.tgz", + "integrity": "sha512-ODiAHvso6JcWJ6ZkHHroVp05EHGhqQN533PtFNBkg8Fy5mERDqsr030AX81M0D69ZcaMvhF92SRckEk2B0HYYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*", + "@types/oauth": "*", + "@types/passport": "*" + } + }, "node_modules/@types/qs": { "version": "6.9.15", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", - "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==", - "dev": true + "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==" }, "node_modules/@types/range-parser": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", - "dev": true + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==" }, "node_modules/@types/send": { "version": "0.17.4", "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", - "dev": true, "dependencies": { "@types/mime": "^1", "@types/node": "*" @@ -200,7 +249,6 @@ "version": "1.15.7", "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", - "dev": true, "dependencies": { "@types/http-errors": "*", "@types/node": "*", @@ -315,6 +363,15 @@ "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==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/bcrypt": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", @@ -683,6 +740,31 @@ "node": ">= 0.10.0" } }, + "node_modules/express-session": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.18.0.tgz", + "integrity": "sha512-m93QLWr0ju+rOwApSsyso838LQwgfs44QtOP/WBiwtAgPIo/SAh1a5c6nn2BR6mFNZehTpqKDESzP+fRHVbxwQ==", + "license": "MIT", + "dependencies": { + "cookie": "0.6.0", + "cookie-signature": "1.0.7", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-headers": "~1.0.2", + "parseurl": "~1.3.3", + "safe-buffer": "5.2.1", + "uid-safe": "~2.1.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/express-session/node_modules/cookie-signature": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", + "license": "MIT" + }, "node_modules/finalhandler": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", @@ -1433,6 +1515,12 @@ "set-blocking": "^2.0.0" } }, + "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==", + "license": "MIT" + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -1463,6 +1551,15 @@ "node": ">= 0.8" } }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -1479,6 +1576,64 @@ "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==", + "license": "MIT", + "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-facebook": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/passport-facebook/-/passport-facebook-3.0.0.tgz", + "integrity": "sha512-K/qNzuFsFISYAyC1Nma4qgY/12V3RSLFdFVsPKXiKZt434wOvthFW1p7zKa1iQihQMRhaWorVE1o3Vi1o+ZgeQ==", + "license": "MIT", + "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==", + "license": "MIT", + "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-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -1492,6 +1647,11 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, + "node_modules/pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" + }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -1531,6 +1691,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -1819,6 +1988,24 @@ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" }, + "node_modules/uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "license": "MIT", + "dependencies": { + "random-bytes": "~1.0.0" + }, + "engines": { + "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==", + "license": "MIT" + }, "node_modules/undici-types": { "version": "6.19.8", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", diff --git a/package.json b/package.json index 2f9f586..ea7ec19 100644 --- a/package.json +++ b/package.json @@ -10,21 +10,26 @@ "author": "", "license": "ISC", "dependencies": { + "@types/express-session": "^1.18.0", "@types/jsonwebtoken": "^9.0.6", "@types/uuid": "^10.0.0", "bcrypt": "^5.1.1", "dotenv": "^16.4.5", "express": "^4.19.2", + "express-session": "^1.18.0", "joi": "^17.13.3", "jsonwebtoken": "^9.0.2", "mongoose": "^8.6.1", "multer": "^1.4.5-lts.1", + "passport": "^0.7.0", + "passport-facebook": "^3.0.0", "uuid": "^10.0.0" }, "devDependencies": { "@types/bcrypt": "^5.0.2", "@types/express": "^4.17.21", "@types/multer": "^1.4.12", - "@types/node": "^22.5.4" + "@types/node": "^22.5.4", + "@types/passport-facebook": "^3.0.3" } } diff --git a/src/bootstrab.ts b/src/bootstrab.ts index c48507f..8dbb283 100644 --- a/src/bootstrab.ts +++ b/src/bootstrab.ts @@ -4,12 +4,14 @@ import { globalHandeling } from "./middleware/errorHandeling/globalHandeling" import { postRouter } from "./modules/post/post.routes" import { commentRouter } from "./modules/comment/comments.routes" import { replyRouter } from "./modules/replie/reply.routes" +import facebookRouter from "./modules/user/socialNetworkLogin" export const bootstrab= function(app:Router):void{ app.use('/users',userRouter) app.use('/posts',postRouter) app.use('/comments',commentRouter) app.use('/replies',replyRouter) +app.use(facebookRouter) app.use(globalHandeling) } \ No newline at end of file diff --git a/src/middleware/validate.ts b/src/middleware/validate.ts index 66614a9..b1f8695 100644 --- a/src/middleware/validate.ts +++ b/src/middleware/validate.ts @@ -1,11 +1,14 @@ -import { Request,Response,NextFunction } from "express"; +import { Request, Response, NextFunction } from "express"; import { AppError } from "../utils/appError"; -const validate = (schema:any) => { - return (req:Request, res:Response, next:NextFunction) => { - let files = () => {return {[`${req.file?.fieldname}`]: req.file };} - - +const validate = (schema: any) => { + return (req: Request, res: Response, next: NextFunction) => { + let files = () => { + if(!req.file) return {} + return { [`${req.file?.fieldname}`]: req.file }; + }; + console.log(req.query); + const { error } = schema.validate( { ...req.body, @@ -16,7 +19,7 @@ const validate = (schema:any) => { { abortEarly: false } ); if (!error) return next(); - const errors = error?.details.map((ele:Error)=> ele.message); + const errors = error?.details.map((ele: Error) => ele.message); next(new AppError(errors, 403)); }; }; diff --git a/src/modules/user/socialNetworkLogin.ts b/src/modules/user/socialNetworkLogin.ts new file mode 100644 index 0000000..d0740bf --- /dev/null +++ b/src/modules/user/socialNetworkLogin.ts @@ -0,0 +1,53 @@ +import passport from 'passport' +import { User } from '../../../database/models/userModel'; +import facebook from 'passport-facebook' +import { NextFunction, Request, Response, Router } from 'express'; +const FacebookStrategy=facebook.Strategy +const facebookRouter =Router() +import 'dotenv/config' +import { AppError } from '../../utils/appError'; +import { catchError } from '../../middleware/errorHandeling/catchErrors'; +passport.use( + new FacebookStrategy( + { + clientID:'894388332019012', + clientSecret: 'f3ec0038f9c5e5bff630f117bcf799c5', + callbackURL: 'http://localhost:3000/', + }, + async function ( profile:any, cb:any) { + const user = await User.findOne({ + accountId: profile.id, + provider: 'facebook', + }); + if (!user) { + console.log('Adding new facebook user to DB..'); + const user = new User({ + accountId: profile.id, + name: profile.displayName, + provider: profile.provider, + }); + await user.save(); + // console.log(user); + return cb(null, profile); + } else { + console.log('Facebook User already exist in DB..'); + // console.log(profile); + return cb(null, profile); + } + } + ) +); +facebookRouter.get('/facebook',catchError((req:any,res:any,next:NextFunction)=>{ + passport.authenticate('facebook', (err:any,user:any)=>{ + const userInfo = { + id: req.session.passport.user.id, + displayName: req.session.passport.user.displayName, + provider: req.session.passport.user.provider, + }; + if(err)return next(new AppError('login failed ',401)) + res.json({message:userInfo}) + } ) + + +})); +export default facebookRouter \ No newline at end of file diff --git a/src/modules/user/user.controller.ts b/src/modules/user/user.controller.ts index 19cdfb4..421be4b 100644 --- a/src/modules/user/user.controller.ts +++ b/src/modules/user/user.controller.ts @@ -7,7 +7,6 @@ import { AppError } from "../../utils/appError"; import { IUser } from "./userINTF"; import { removeOldImage } from "../../utils/removeOldImage"; import { Post } from "../../../database/models/postModel"; - const signUp = catchError( async (req: Request, res: Response, next: NextFunction) => { req.body.password = bcrypt.hashSync(req.body.password, 10); diff --git a/src/modules/user/user.validation.ts b/src/modules/user/user.validation.ts index f945f6f..819b5cc 100644 --- a/src/modules/user/user.validation.ts +++ b/src/modules/user/user.validation.ts @@ -3,7 +3,7 @@ import Joi from "joi"; const signupVal=Joi.object({ name:Joi.string().min(5).max(30).required(), email:Joi.string().email().required(), - passowrd:Joi.string().pattern(/^[A-Z][a-zA-Z0-9]{8,40}$/).required(), + password:Joi.string().required(), rePassword:Joi.valid(Joi.ref('passowrd')).required(), bio:Joi.string(), preferences:Joi.string(), @@ -21,7 +21,7 @@ const signupVal=Joi.object({ const signInVal=Joi.object({ email:Joi.string().email().required(), - passowrd:Joi.string().pattern(/^[A-Z][a-zA-Z0-9]{8,40}$/).required() + password:Joi.string().required() }) const updateProfileVal=Joi.object({ name:Joi.string().min(5).max(30),