Showing
14 changed files
with
147 additions
and
21 deletions
| ... | @@ -16,10 +16,15 @@ | ... | @@ -16,10 +16,15 @@ |
| 16 | "@babel/node": "^7.13.13", | 16 | "@babel/node": "^7.13.13", |
| 17 | "@babel/preset-env": "^7.14.1", | 17 | "@babel/preset-env": "^7.14.1", |
| 18 | "axios": "^0.21.1", | 18 | "axios": "^0.21.1", |
| 19 | + "connect-mongo": "^4.4.1", | ||
| 20 | + "dotenv": "^9.0.2", | ||
| 19 | "express": "^4.17.1", | 21 | "express": "^4.17.1", |
| 22 | + "express-session": "^1.17.1", | ||
| 20 | "mongoose": "^5.12.9", | 23 | "mongoose": "^5.12.9", |
| 21 | "morgan": "^1.10.0", | 24 | "morgan": "^1.10.0", |
| 22 | "nodemon": "^2.0.7", | 25 | "nodemon": "^2.0.7", |
| 26 | + "passport": "^0.4.1", | ||
| 27 | + "passport-github2": "^0.1.12", | ||
| 23 | "pug": "^3.0.2" | 28 | "pug": "^3.0.2" |
| 24 | }, | 29 | }, |
| 25 | "devDependencies": { | 30 | "devDependencies": { | ... | ... |
| 1 | import axios from "axios"; | 1 | import axios from "axios"; |
| 2 | +import passport from "passport"; | ||
| 2 | import User from "../models/User"; | 3 | import User from "../models/User"; |
| 3 | 4 | ||
| 4 | const getQuote = async (req,res) =>{ | 5 | const getQuote = async (req,res) =>{ |
| ... | @@ -41,3 +42,40 @@ export const getLogin = (req,res)=>{ | ... | @@ -41,3 +42,40 @@ export const getLogin = (req,res)=>{ |
| 41 | export const handleUsers = (req,res)=>{ | 42 | export const handleUsers = (req,res)=>{ |
| 42 | res.render("users",{pageTitle:"Users"}); | 43 | res.render("users",{pageTitle:"Users"}); |
| 43 | } | 44 | } |
| 45 | + | ||
| 46 | +export const githubLogin = passport.authenticate("github", {scope: [ "user:email" ]}); | ||
| 47 | + | ||
| 48 | +export const githubLoginCallback = async (_, __, profile, done) =>{ | ||
| 49 | + const {_json: {id:githubId, login:githubName, avatar_url:avatarUrl, name, email}} = profile; | ||
| 50 | + | ||
| 51 | + try{ | ||
| 52 | + const user = await User.findOne({email}); | ||
| 53 | + if(user){ | ||
| 54 | + user.githubId = githubId, | ||
| 55 | + user.githubName = githubName | ||
| 56 | + await user.save(); | ||
| 57 | + return done(null, user); | ||
| 58 | + }else{ | ||
| 59 | + const newUser = await User.create({ | ||
| 60 | + githubId, | ||
| 61 | + githubName, | ||
| 62 | + avatarUrl, | ||
| 63 | + name, | ||
| 64 | |||
| 65 | + }); | ||
| 66 | + return done(null, newUser); | ||
| 67 | + } | ||
| 68 | + }catch(error){ | ||
| 69 | + return done(error); | ||
| 70 | + } | ||
| 71 | +}; | ||
| 72 | + | ||
| 73 | +export const postGithubLogin = (req,res)=>{ | ||
| 74 | + const userId = req.user.id; | ||
| 75 | + res.redirect(`/users/${userId}`); | ||
| 76 | +} | ||
| 77 | + | ||
| 78 | +export const logout = (req,res)=>{ | ||
| 79 | + req.logout(); | ||
| 80 | + res.redirect("/"); | ||
| 81 | +} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| 1 | import mongoose from "mongoose"; | 1 | import mongoose from "mongoose"; |
| 2 | 2 | ||
| 3 | -mongoose.connect("mongodb://127.0.0.1:27017/dev-profile",{ | 3 | +mongoose.connect(process.env.DB_URL,{ |
| 4 | useNewUrlParser: true, | 4 | useNewUrlParser: true, |
| 5 | useFindAndModify: false, | 5 | useFindAndModify: false, |
| 6 | - useUnifiedTopology: true | 6 | + useUnifiedTopology: true, |
| 7 | + useCreateIndex: true | ||
| 7 | } | 8 | } |
| 8 | ); | 9 | ); |
| 9 | 10 | ... | ... |
| 1 | export const localsMiddleware = (req,res,next) => { | 1 | export const localsMiddleware = (req,res,next) => { |
| 2 | res.locals.siteName = "Dev Profile"; | 2 | res.locals.siteName = "Dev Profile"; |
| 3 | + res.locals.loggedUser = req.user || null; | ||
| 4 | + | ||
| 3 | next(); | 5 | next(); |
| 6 | +}; | ||
| 7 | + | ||
| 8 | +export const onlyPublic = (req, res, next) => { | ||
| 9 | + if(req.user){ | ||
| 10 | + res.redirect("/"); | ||
| 11 | + } else { | ||
| 12 | + next(); | ||
| 13 | + } | ||
| 14 | +}; | ||
| 15 | + | ||
| 16 | +export const onlyPrivate = (req, res, next) => { | ||
| 17 | + if(req.user){ | ||
| 18 | + next(); | ||
| 19 | + } else { | ||
| 20 | + res.redirect("/"); | ||
| 21 | + } | ||
| 4 | }; | 22 | }; |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| ... | @@ -7,12 +7,14 @@ const UserSchema = new mongoose.Schema({ | ... | @@ -7,12 +7,14 @@ const UserSchema = new mongoose.Schema({ |
| 7 | }, | 7 | }, |
| 8 | email: { | 8 | email: { |
| 9 | type: String, | 9 | type: String, |
| 10 | - trim: true | 10 | + trim: true, |
| 11 | + unique: true | ||
| 11 | }, | 12 | }, |
| 12 | avatarUrl: String, | 13 | avatarUrl: String, |
| 13 | githubId: { | 14 | githubId: { |
| 14 | type: Number, | 15 | type: Number, |
| 15 | - required: "GitHub id is required" | 16 | + required: "GitHub id is required", |
| 17 | + unique: true | ||
| 16 | }, | 18 | }, |
| 17 | githubName: { | 19 | githubName: { |
| 18 | type: String, | 20 | type: String, |
| ... | @@ -40,6 +42,13 @@ const UserSchema = new mongoose.Schema({ | ... | @@ -40,6 +42,13 @@ const UserSchema = new mongoose.Schema({ |
| 40 | } | 42 | } |
| 41 | }); | 43 | }); |
| 42 | 44 | ||
| 45 | +UserSchema.static("formatTech", function(tech){ | ||
| 46 | + return tech.split(","); | ||
| 47 | +}); | ||
| 48 | +UserSchema.static("formatCareer",function(career){ | ||
| 49 | + return career.split(","); | ||
| 50 | +}); | ||
| 51 | + | ||
| 43 | const User = mongoose.model("User", UserSchema); | 52 | const User = mongoose.model("User", UserSchema); |
| 44 | 53 | ||
| 45 | 54 | ... | ... |
src/passport.js
0 → 100644
| 1 | +import passport from "passport"; | ||
| 2 | +import GithubStrategy from "passport-github2"; | ||
| 3 | +import { githubLoginCallback } from "./controllers/userController"; | ||
| 4 | +import User from "./models/User"; | ||
| 5 | + | ||
| 6 | +passport.use(new GithubStrategy( | ||
| 7 | + { | ||
| 8 | + clientID: process.env.GH_ID, | ||
| 9 | + clientSecret: process.env.GH_SECRET, | ||
| 10 | + callbackURL: `http://localhost:5500/auth/github/callback` | ||
| 11 | + }, | ||
| 12 | + githubLoginCallback | ||
| 13 | +) | ||
| 14 | +); | ||
| 15 | + | ||
| 16 | +passport.serializeUser(function(user, done) { | ||
| 17 | + done(null, user); | ||
| 18 | + }); | ||
| 19 | + | ||
| 20 | + passport.deserializeUser(function(user, done) { | ||
| 21 | + done(null, user); | ||
| 22 | + }); | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | import express from "express"; | 1 | import express from "express"; |
| 2 | -import { getJoin, getLogin, handleHome } from "../controllers/userController"; | 2 | +import passport from "passport"; |
| 3 | +import { getJoin, getLogin, githubLogin, handleHome, logout, postGithubLogin } from "../controllers/userController"; | ||
| 4 | +import { onlyPrivate, onlyPublic } from "../middlewares"; | ||
| 3 | 5 | ||
| 4 | 6 | ||
| 5 | 7 | ||
| 6 | const globalRouter = express.Router(); | 8 | const globalRouter = express.Router(); |
| 7 | 9 | ||
| 8 | globalRouter.get("/",handleHome); | 10 | globalRouter.get("/",handleHome); |
| 9 | -globalRouter.get("/join", getJoin); | 11 | +globalRouter.get("/join", onlyPublic, getJoin); |
| 10 | -globalRouter.get("/login",getLogin); | 12 | +globalRouter.get("/login", onlyPublic, getLogin); |
| 13 | +globalRouter.get("/logout", onlyPrivate, logout); | ||
| 11 | 14 | ||
| 15 | +globalRouter.get("/auth/github", githubLogin); | ||
| 16 | +globalRouter.get( | ||
| 17 | + "/auth/github/callback", | ||
| 18 | + passport.authenticate("github",{failureRedirect: "/login"}), | ||
| 19 | + postGithubLogin | ||
| 20 | +); | ||
| 12 | 21 | ||
| 13 | export default globalRouter; | 22 | export default globalRouter; |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| 1 | import express from "express"; | 1 | import express from "express"; |
| 2 | import { getEditProfile, getUserDetail, handleUsers, postEditProfile } from "../controllers/userController"; | 2 | import { getEditProfile, getUserDetail, handleUsers, postEditProfile } from "../controllers/userController"; |
| 3 | +import { onlyPrivate } from "../middlewares"; | ||
| 3 | 4 | ||
| 4 | 5 | ||
| 5 | const userRouter = express.Router(); | 6 | const userRouter = express.Router(); |
| 6 | 7 | ||
| 7 | userRouter.get("/",handleUsers); | 8 | userRouter.get("/",handleUsers); |
| 8 | 9 | ||
| 9 | -userRouter.get("/edit-profile", getEditProfile); | 10 | +userRouter.get("/edit-profile", onlyPrivate, getEditProfile); |
| 10 | -userRouter.post("/edit-profile", postEditProfile); | 11 | +userRouter.post("/edit-profile", onlyPrivate, postEditProfile); |
| 11 | 12 | ||
| 12 | userRouter.get("/:id", getUserDetail); | 13 | userRouter.get("/:id", getUserDetail); |
| 13 | 14 | ... | ... |
| 1 | import express from "express"; | 1 | import express from "express"; |
| 2 | import path from "path"; | 2 | import path from "path"; |
| 3 | import morgan from "morgan"; | 3 | import morgan from "morgan"; |
| 4 | +import session from "express-session"; | ||
| 5 | +import passport from "passport"; | ||
| 6 | +import MongoStore from "connect-mongo"; | ||
| 4 | import globalRouter from "./routers/globalRouter"; | 7 | import globalRouter from "./routers/globalRouter"; |
| 5 | import userRouter from "./routers/userRouter"; | 8 | import userRouter from "./routers/userRouter"; |
| 6 | import { localsMiddleware } from "./middlewares"; | 9 | import { localsMiddleware } from "./middlewares"; |
| 7 | - | 10 | +import "./passport"; |
| 8 | 11 | ||
| 9 | 12 | ||
| 10 | const app = express(); | 13 | const app = express(); |
| ... | @@ -16,7 +19,17 @@ app.use(express.static(path.join(__dirname, "static"))); | ... | @@ -16,7 +19,17 @@ app.use(express.static(path.join(__dirname, "static"))); |
| 16 | app.use(morgan("dev")); | 19 | app.use(morgan("dev")); |
| 17 | app.use(express.json()); | 20 | app.use(express.json()); |
| 18 | app.use(express.urlencoded({ extended: true })); | 21 | app.use(express.urlencoded({ extended: true })); |
| 19 | - | 22 | +app.use( |
| 23 | + session({ | ||
| 24 | + secret: process.env.COOKIE_SECRET, | ||
| 25 | + resave: true, | ||
| 26 | + saveUninitialized: false, | ||
| 27 | + store: MongoStore.create({mongoUrl: process.env.DB_URL}) | ||
| 28 | + }) | ||
| 29 | +); | ||
| 30 | + | ||
| 31 | +app.use(passport.initialize()); | ||
| 32 | +app.use(passport.session()); | ||
| 20 | 33 | ||
| 21 | app.use(localsMiddleware); | 34 | app.use(localsMiddleware); |
| 22 | app.use("/", globalRouter); | 35 | app.use("/", globalRouter); | ... | ... |
| ... | @@ -4,7 +4,7 @@ block content | ... | @@ -4,7 +4,7 @@ block content |
| 4 | i.fas.fa-location-arrow | 4 | i.fas.fa-location-arrow |
| 5 | h3 Start with GitHub! | 5 | h3 Start with GitHub! |
| 6 | button.login-github | 6 | button.login-github |
| 7 | - a(href="#") | 7 | + a(href="/auth/github") |
| 8 | span | 8 | span |
| 9 | i.fab.fa-github | 9 | i.fab.fa-github |
| 10 | |Join with GitHub | 10 | |Join with GitHub | ... | ... |
| ... | @@ -4,7 +4,7 @@ block content | ... | @@ -4,7 +4,7 @@ block content |
| 4 | i.fas.fa-location-arrow | 4 | i.fas.fa-location-arrow |
| 5 | h3 Login with GitHub! | 5 | h3 Login with GitHub! |
| 6 | button.login-github | 6 | button.login-github |
| 7 | - a(href="#") | 7 | + a(href="/auth/github") |
| 8 | span | 8 | span |
| 9 | i.fab.fa-github | 9 | i.fab.fa-github |
| 10 | |Login with GitHub | 10 | |Login with GitHub | ... | ... |
| ... | @@ -2,11 +2,18 @@ header.header | ... | @@ -2,11 +2,18 @@ header.header |
| 2 | .header__wrapper | 2 | .header__wrapper |
| 3 | .header__column | 3 | .header__column |
| 4 | ul | 4 | ul |
| 5 | - li | ||
| 6 | - a(href="/") Home | ||
| 7 | - li | ||
| 8 | - a(href="/join") Join | ||
| 9 | - li | ||
| 10 | - a(href="/login") Log In | ||
| 11 | - li | ||
| 12 | - a(href="/users/edit-profile") Edit Profile | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 5 | + if !loggedUser | ||
| 6 | + li | ||
| 7 | + a(href="/") Home | ||
| 8 | + li | ||
| 9 | + a(href="/join") Join | ||
| 10 | + li | ||
| 11 | + a(href="/login") Log In | ||
| 12 | + | ||
| 13 | + else | ||
| 14 | + li | ||
| 15 | + a(href="/") Home | ||
| 16 | + li | ||
| 17 | + a(href="/users/edit-profile") Edit Profile | ||
| 18 | + li | ||
| 19 | + a(href="/logout") Log Out | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| ... | @@ -5,6 +5,7 @@ block content | ... | @@ -5,6 +5,7 @@ block content |
| 5 | .user-quote | 5 | .user-quote |
| 6 | h2=quote | 6 | h2=quote |
| 7 | h3=author | 7 | h3=author |
| 8 | + hr | ||
| 8 | .user-profile | 9 | .user-profile |
| 9 | .user-profile__column | 10 | .user-profile__column |
| 10 | img(src="#") | 11 | img(src="#") |
| ... | @@ -20,6 +21,7 @@ block content | ... | @@ -20,6 +21,7 @@ block content |
| 20 | h3 TECH | 21 | h3 TECH |
| 21 | h3 CAREER | 22 | h3 CAREER |
| 22 | h3 SELF-INTRODUCTION | 23 | h3 SELF-INTRODUCTION |
| 24 | + hr | ||
| 23 | .user-status | 25 | .user-status |
| 24 | .user-status__contributions | 26 | .user-status__contributions |
| 25 | img(src="http://ghchart.rshah.org/lsj8706" alt="Name Your Github chart") | 27 | img(src="http://ghchart.rshah.org/lsj8706" alt="Name Your Github chart") | ... | ... |
-
Please register or login to post a comment