Showing
24 changed files
with
367 additions
and
28 deletions
This diff is collapsed. Click to expand it.
... | @@ -16,8 +16,12 @@ | ... | @@ -16,8 +16,12 @@ |
16 | }, | 16 | }, |
17 | "dependencies": { | 17 | "dependencies": { |
18 | "babel-loader": "^8.2.5", | 18 | "babel-loader": "^8.2.5", |
19 | + "bcrypt": "^5.0.1", | ||
20 | + "connect-mongo": "^4.6.0", | ||
19 | "dotenv": "^16.0.1", | 21 | "dotenv": "^16.0.1", |
20 | "express": "^4.18.1", | 22 | "express": "^4.18.1", |
23 | + "express-session": "^1.17.3", | ||
24 | + "mongoose": "^6.3.5", | ||
21 | "node-fetch": "^2.6.1", | 25 | "node-fetch": "^2.6.1", |
22 | "pug": "^3.0.2" | 26 | "pug": "^3.0.2" |
23 | } | 27 | } | ... | ... |
1 | -export const home = (req,res)=>{ | 1 | +import fetch from"node-fetch"; |
2 | - return res.render("home",{siteTitle: "movie!",pageTitle:"home Page!"}); | 2 | +import User from "../../models/User" |
3 | +import bcrypt from "bcrypt" | ||
4 | + | ||
5 | +export const home = async(req,res)=>{ | ||
6 | + const KEY= process.env.API_KEY | ||
7 | + const data = await fetch(`https://api.themoviedb.org/3/trending/movie/week?api_key=${KEY}`,{ | ||
8 | + method:"GET", | ||
9 | + }) | ||
10 | + const movies = await data.json(); | ||
11 | + return res.render("home",{siteTitle: "movie!",pageTitle:"home Page!",movies: movies.results}); | ||
12 | +} | ||
13 | + | ||
14 | +export const getJoin = (req,res) =>{ | ||
15 | + res.render('join.pug',{pageTitle:"Join!",siteTitle:"movie!"}) | ||
16 | +} | ||
17 | + | ||
18 | +export const postJoin = async (req,res) =>{ | ||
19 | + const { email, | ||
20 | + username, | ||
21 | + password, | ||
22 | + passwordcheck, } = req.body; | ||
23 | + const pageTitle = "Join"; | ||
24 | + if (password !== passwordcheck) { | ||
25 | + return res.status(400).render("join.pug", { | ||
26 | + pageTitle, | ||
27 | + errorMessage: "Password confirmation does not match.", | ||
28 | + }); | ||
29 | + } | ||
30 | + const exists = await User.exists({ $or: [{ username }, { email }] }); | ||
31 | + if (exists) { | ||
32 | + return res.status(400).render("join", { | ||
33 | + pageTitle, | ||
34 | + errorMessage: "This username/email is already taken.", | ||
35 | + }); | ||
36 | + } | ||
37 | + try { | ||
38 | + await User.create({ | ||
39 | + username, | ||
40 | + email, | ||
41 | + password, | ||
42 | + }); | ||
43 | + return res.redirect("/login"); | ||
44 | + } catch(error){ | ||
45 | + return res.status(400).res.render("join", { | ||
46 | + pageTitle: "Upload Video" , | ||
47 | + errorMessage: error._message, | ||
48 | + }); | ||
49 | +} | ||
3 | } | 50 | } |
4 | 51 | ||
5 | -export const join= (req,res) =>{ | 52 | +export const getLogin = (req,res)=>{ |
6 | - return res.send("hello this is joinpage!"); | 53 | + return res.render("login",{siteTitle:"movie!",pageTitle:"Login!"}) |
7 | } | 54 | } |
8 | 55 | ||
9 | -export const login = (req,res)=>{ | 56 | +export const postLogin = async (req,res) => |
10 | - return res.send("hello this is login!"); | 57 | +{ |
58 | + const PAGETITLE = "Login" | ||
59 | + const {username,password} = req.body; | ||
60 | + console.log(username,password) | ||
61 | + const user = await User.findOne({username}); | ||
62 | + console.log(user) | ||
63 | + if(!user){ | ||
64 | + return res.status(400).render("login",{pageTitle:PAGETITLE,error:"An account with that username is not found"}) | ||
65 | + } | ||
66 | + if (user.isO_Auth) | ||
67 | + return res.status(400).render("login",{pageTitle:PAGETITLE,error:"Please login with Github"}) | ||
68 | + const ok = await bcrypt.compare(password,user.password); | ||
69 | + if(!ok){ | ||
70 | + return res.status(400).render("login",{pageTitle:PAGETITLE,error:"something wrong..."}) | ||
71 | + } | ||
72 | + req.session.loggedIn = true; | ||
73 | + req.session.user = user; | ||
74 | + return res.redirect('/'); | ||
75 | +} | ||
76 | + | ||
77 | +export const startGithubLogin = (req,res) => | ||
78 | +{ | ||
79 | + const baseURL = `https://github.com/login/oauth/authorize` | ||
80 | + const config = { | ||
81 | + client_id: process.env.O_Auth_client_id, | ||
82 | + allow_signup:false, | ||
83 | + scope:"read:user user:email" | ||
84 | + } | ||
85 | + const params = new URLSearchParams(config).toString(); | ||
86 | + const finalURL = `${baseURL}?${params}` | ||
87 | + console.log(finalURL); | ||
88 | + return res.redirect(finalURL); | ||
89 | +} | ||
90 | + | ||
91 | +export const finishGithubLogin = async (req,res) => | ||
92 | +{ | ||
93 | + | ||
94 | + const config = { | ||
95 | + client_id: process.env.O_AUTH_CLIENT_ID, | ||
96 | + client_secret : process.env.O_Auth_scret, | ||
97 | + code: req.query.code | ||
98 | + } | ||
99 | + const params = new URLSearchParams(config).toString(); | ||
100 | + const baseURL = `https://github.com/login/oauth/access_token`; | ||
101 | + const finalURL = `${baseURL}?${params}`; | ||
102 | + console.log(req.query); | ||
103 | + const data = await fetch(finalURL,{ | ||
104 | + method:"POST", | ||
105 | + headers:{ | ||
106 | + Accept: "application/json", | ||
107 | + } | ||
108 | + }); | ||
109 | + const token = await data.json(); | ||
110 | + if("access_token" in token) | ||
111 | + { | ||
112 | + const {access_token} = token; | ||
113 | + const apiUrl = "https://api.github.com" | ||
114 | + const getUserData = await fetch(`${apiUrl}/user`,{ | ||
115 | + method:"GET", | ||
116 | + headers:{ | ||
117 | + Authorization: `token ${access_token}` | ||
118 | + } | ||
119 | + }); | ||
120 | + const emailData = await ( | ||
121 | + await fetch(`${apiUrl}/user/emails`,{ | ||
122 | + method:"GET", | ||
123 | + headers:{ | ||
124 | + Authorization: `token ${access_token}` | ||
125 | + } | ||
126 | + }) | ||
127 | + ).json(); | ||
128 | + const emailObj = emailData.find((email) => email.primary === true && email.verified === true); | ||
129 | + if(!emailObj){ | ||
130 | + return res.status(400).redirect('/login'); | ||
131 | + } | ||
132 | + let user = await User.findOne({email: emailObj.email}); | ||
133 | + if(!user){ | ||
134 | + user = await User.create({ | ||
135 | + email:emailObj.email, | ||
136 | + username:userData.login, | ||
137 | + password:"", | ||
138 | + isO_Auth: true, | ||
139 | + }); | ||
140 | + } | ||
141 | + req.session.loggedIn = true, | ||
142 | + req.session.user = user; | ||
143 | + return res.redirect("/"); | ||
144 | + }else{ | ||
145 | + res.status(400).redirect("/login") | ||
146 | + } | ||
11 | } | 147 | } |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
... | @@ -13,6 +13,34 @@ export const showMovies = (req,res) =>{ | ... | @@ -13,6 +13,34 @@ export const showMovies = (req,res) =>{ |
13 | res.send("movie home"); | 13 | res.send("movie home"); |
14 | } | 14 | } |
15 | 15 | ||
16 | -export const movieInformation = (req,res)=>{ | 16 | +export const movieInformation = async (req,res)=>{ |
17 | - res.send("movie detail"); | 17 | + const {id}= req.params; |
18 | + const KEY= process.env.API_KEY | ||
19 | + const data = await fetch(`https://api.themoviedb.org/3/movie/${id}?api_key=${KEY}&language=ko-KR`) | ||
20 | + const info = await data.json(); | ||
21 | + res.render('detail.pug',{siteTitle:"movie!",pageTitle:`${info.original_title}`,info}) | ||
22 | +} | ||
23 | + | ||
24 | +export const getDiscover = (req, res)=>{ | ||
25 | + res.render('discover',{siteTitle:"movie!"}) | ||
26 | +} | ||
27 | + | ||
28 | +export const postDiscover = async (req, res)=>{ | ||
29 | + const {year, genre,rating} = req.body | ||
30 | + console.log(year,genre,rating) | ||
31 | + const KEY= process.env.API_KEY | ||
32 | + const genreData = await fetch(`https://api.themoviedb.org/3/genre/movie/list?api_key=${KEY}&language=en-US`) | ||
33 | + const genres = await genreData.json() | ||
34 | + const target = genres.genres.filter(index => index.name === genre) | ||
35 | + const genreId = target[0].id | ||
36 | + | ||
37 | + const moviesData = await fetch(` | ||
38 | + https://api.themoviedb.org/3/discover/movie?api_key=${KEY}&language=en-US&sort_by=popularity.desc&include_adult=false&include_video=false&page=1&year=${year}&vote_average.gte=${rating}&with_genres=28%2C12&with_watch_monetization_types=flatrate`, | ||
39 | + { | ||
40 | + method:"GET" | ||
41 | + }) | ||
42 | + const Result = await moviesData.json() | ||
43 | + const movies = Result.results | ||
44 | + console.log(movies) | ||
45 | + return res.render(`discoverResult.pug`,{siteTitle:"movie!",movies}) | ||
18 | } | 46 | } | ... | ... |
1 | -export const userId = (req,res) =>{ | 1 | +export const logout =(req,res)=>{ |
2 | - //getMovies(); | 2 | + req.session.destroy(); |
3 | - res.send("user page"); | 3 | + return res.redirect("/") |
4 | } | 4 | } |
5 | - | ||
6 | -export const userLikemovie = (req,res) =>{ | ||
7 | - //getMovies(); | ||
8 | - res.send("user's favorite"); | ||
9 | -} | ||
10 | - | ... | ... |
src/backend/db.js
0 → 100644
src/backend/init.js
0 → 100644
src/backend/middlewares.js
0 → 100644
src/backend/routers/apiRouters.js
0 → 100644
File mode changed
1 | import express from "express"; | 1 | import express from "express"; |
2 | -import {home,join,login} from "../controllers/globalController" | 2 | +import {getJoin, getLogin, home, postJoin, postLogin} from "../controllers/globalController" |
3 | +import { logout } from "../controllers/usersController"; | ||
3 | const globalRouter = express.Router(); | 4 | const globalRouter = express.Router(); |
4 | 5 | ||
5 | globalRouter.get('/',home); | 6 | globalRouter.get('/',home); |
6 | -globalRouter.get('/join',join); | 7 | +globalRouter.get("/logout",logout) |
7 | -globalRouter.get('/login',login); | 8 | +globalRouter.route('/join').get(getJoin).post(postJoin) |
9 | +globalRouter.route('/login').get(getLogin).post(postLogin) | ||
8 | export default globalRouter | 10 | 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 { showMovies, movieInformation } from "../controllers/movieController"; | 2 | +import { showMovies, movieInformation, getDiscover, postDiscover } from "../controllers/movieController"; |
3 | 3 | ||
4 | const movieRouter = express.Router(); | 4 | const movieRouter = express.Router(); |
5 | 5 | ||
6 | movieRouter.get('/',showMovies); | 6 | movieRouter.get('/',showMovies); |
7 | 7 | ||
8 | -movieRouter.get('/:id', movieInformation); | 8 | +movieRouter.get('/:id(\\d+)', movieInformation); |
9 | + | ||
10 | +movieRouter.route('/discover/').get(getDiscover).post(postDiscover) | ||
11 | + | ||
9 | 12 | ||
10 | export default movieRouter; | 13 | export default movieRouter; |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
1 | import express from "express"; | 1 | import express from "express"; |
2 | -import { userId, userLikemovie } from "../controllers/usersController"; | 2 | +import { finishGithubLogin, startGithubLogin } from "../controllers/globalController"; |
3 | 3 | ||
4 | const userRouter = express.Router(); | 4 | const userRouter = express.Router(); |
5 | 5 | ||
6 | -userRouter.get('/:id(\\d+)', userId); | 6 | +userRouter.get("/github/start",startGithubLogin) |
7 | -userRouter.get('/likemovie', userLikemovie); | 7 | +userRouter.get("/github/finish",finishGithubLogin) |
8 | 8 | ||
9 | export default userRouter | 9 | export default userRouter |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
... | @@ -2,14 +2,29 @@ import express from "express" | ... | @@ -2,14 +2,29 @@ import express from "express" |
2 | import global from "./routers/globalRouter"; | 2 | import global from "./routers/globalRouter"; |
3 | import movies from "./routers/movieRouter"; | 3 | import movies from "./routers/movieRouter"; |
4 | import users from "./routers/userRouter"; | 4 | import users from "./routers/userRouter"; |
5 | +import session from "express-session"; | ||
6 | +import MongoStore from "connect-mongo"; | ||
7 | +import { editLocals } from "./middlewares"; | ||
5 | 8 | ||
6 | const PORT = 3000 | 9 | const PORT = 3000 |
7 | const app = express(); | 10 | const app = express(); |
8 | 11 | ||
12 | + | ||
13 | +app.use(express.json()) | ||
14 | +app.use(express.urlencoded({extend: true})) | ||
15 | +app.use(session({ | ||
16 | + secret:process.env.COOKIE_SCRET, | ||
17 | + resave:false, | ||
18 | + saveUninitialized:false, | ||
19 | + store: MongoStore.create({mongoUrl: process.env.DB_URL}) | ||
20 | +})) | ||
21 | + | ||
9 | app.set('view engine',"pug"); | 22 | app.set('view engine',"pug"); |
10 | app.set("views",process.cwd() +"/src/views"); | 23 | app.set("views",process.cwd() +"/src/views"); |
24 | +app.use(editLocals); | ||
11 | app.use('/',global); | 25 | app.use('/',global); |
12 | app.use('/movies',movies); | 26 | app.use('/movies',movies); |
13 | app.use('/users',users) | 27 | app.use('/users',users) |
14 | 28 | ||
15 | -app.listen(PORT,() => console.log(`The Server is running on http://localhost:${PORT}`)); | 29 | +export default app |
30 | + | ... | ... |
src/models/User.js
0 → 100644
1 | +import bcrypt from "bcrypt"; | ||
2 | +import mongoose from "mongoose"; | ||
3 | + | ||
4 | +const userSchema = new mongoose.Schema({ | ||
5 | + email: { type: String, required: true, unique: true }, | ||
6 | + username: { type: String, unique: true }, | ||
7 | + password: { type: String, }, | ||
8 | + likeMovies: [{type: String}], | ||
9 | + isO_Auth: {type:Boolean,default:false} | ||
10 | +}); | ||
11 | + | ||
12 | +userSchema.pre('save', async function(){ | ||
13 | + console.log("Users password:", this.password); | ||
14 | + this.password = await bcrypt.hash(this.password, 5);`` | ||
15 | + console.log("Users password:", this.password); | ||
16 | +}) | ||
17 | + | ||
18 | +const User = mongoose.model("User", userSchema); | ||
19 | +export default User; | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
src/views/detail.pug
0 → 100644
1 | +extends layout.pug | ||
2 | +include mixins/trending.pug | ||
3 | + | ||
4 | +block content | ||
5 | + div | ||
6 | + h1=pageTitle | ||
7 | + img(src=`https://www.themoviedb.org/t/p/w600_and_h900_bestv2${info.poster_path}`) | ||
8 | + div | ||
9 | + span=info.overview | ||
10 | + br | ||
11 | + span | ||
12 | + a(href=`https://www.themoviedb.org/movie/${info.id}`) The movie DB에서 영화정보 보기 → | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
src/views/discover.pug
0 → 100644
1 | +extends layout.pug | ||
2 | + | ||
3 | +block content | ||
4 | + form(method="POST") | ||
5 | + select(name="year") | ||
6 | + option(value="" selected) 년도선택 | ||
7 | + option(value="2017") 2017 | ||
8 | + option(value="2018") 2018 | ||
9 | + option(value="2019") 2019 | ||
10 | + option(value="2020") 2020 | ||
11 | + option(value="2021") 2021 | ||
12 | + option(value="2022") 2022 | ||
13 | + select(name="genre") | ||
14 | + option(value="") 장르 선택 | ||
15 | + option(value="Action") 액션 | ||
16 | + option(value="Adventure") 어드벤쳐 | ||
17 | + option(value="Animation") 애니메이션 | ||
18 | + option(value="Comedy") 코미디 | ||
19 | + option(value="Crime") 범죄 | ||
20 | + option(value="Documentary") 다큐 | ||
21 | + option(value="Drama") 드라마 | ||
22 | + option(value="Family") 가족영화 | ||
23 | + option(value="Fantasy") 판타지 | ||
24 | + option(value="History") 역사 | ||
25 | + option(value="Horror") 호러 | ||
26 | + option(value="Music") 음악 | ||
27 | + option(value="Mystery") 미스터리 | ||
28 | + option(value="Romance") 로멘스 | ||
29 | + option(value="Science Fiction") 공상과학 | ||
30 | + option(value="TV Movie") Tv영화 | ||
31 | + option(value="Thriller") 스릴러 | ||
32 | + option(value="War") 전쟁 | ||
33 | + option(value="Western") 서부영화 | ||
34 | + select(name="rating") | ||
35 | + option(value="") 평점 선택 | ||
36 | + option(value="5.0") 5.0 | ||
37 | + option(value="6.0") 6.0 | ||
38 | + option(value="7.0") 7.0 | ||
39 | + option(value="8.0") 8.0 | ||
40 | + option(value="9.0") 9.0 | ||
41 | + input(value="영화 검색!" type="submit") | ||
42 | + | ||
43 | + |
src/views/discoverResult.pug
0 → 100644
src/views/join.pug
0 → 100644
1 | +extends layout.pug | ||
2 | + | ||
3 | +block content | ||
4 | + if errorMessage | ||
5 | + h3=errorMessage | ||
6 | + h1=pageTitle | ||
7 | + form(method="POST") | ||
8 | + input(name="email" placeholder="your email plz" required type="email") | ||
9 | + input(name="username" placeholder="your nickname!" required) | ||
10 | + input(name="password" placeholder="your password" required type="password") | ||
11 | + input(name="passwordcheck" placeholder="passwowrd validation" required type="password") | ||
12 | + input(value="join now!" type="submit") | ||
13 | + hr | ||
14 | + span | ||
15 | + a(href="/login") you already have account? login now! → | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
src/views/login.pug
0 → 100644
1 | +extends layout.pug | ||
2 | + | ||
3 | +block content | ||
4 | + if errorMessage | ||
5 | + h3=errorMessage | ||
6 | + h1=pageTitle | ||
7 | + form(method="POST") | ||
8 | + input(name="username" placeholder="your username plz" required type="text") | ||
9 | + input(name="password" placeholder="your password" required type="password") | ||
10 | + input(value="login now!" type="submit") | ||
11 | + hr | ||
12 | + span | ||
13 | + a(href="/join") you don't have account? Join now! → | ||
14 | + a(href="/users/github/start") Continue with Github → | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
src/views/mixins/movies.pug
0 → 100644
src/views/mixins/trending.pug
0 → 100644
... | @@ -4,4 +4,12 @@ header | ... | @@ -4,4 +4,12 @@ header |
4 | li | 4 | li |
5 | a(href="/") Home | 5 | a(href="/") Home |
6 | li | 6 | li |
7 | - a(href="/movies") Movies | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
7 | + a(href="/movies/discover/") Movies | ||
8 | + if loggedIn | ||
9 | + li | ||
10 | + a(href="/logout") logout | ||
11 | + else | ||
12 | + li | ||
13 | + a(href="/login") login | ||
14 | + li | ||
15 | + a(href="/join") join | ||
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
-
Please register or login to post a comment