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