Flare-k

[Add] Express Flash

......@@ -11,6 +11,7 @@
📺 [KhuTube](http://www.khutube.tk:4000/)
위 주소는 실제 EC2 서버에 배포한 주소입니다. (불필요한 업로드는 삼가 주시기 바랍니다.)
현재는 사용하지 않는 주소입니다.(2020.08.29 기준)
This is the address that deployed to the actual EC2 server. (Please refrain from uploading unnecessary files.)
......@@ -108,4 +109,4 @@ I just recommend run both at the same time.
## Contact
이용하시다가 궁금한 점이 있으시면 이쪽으로 연락 부탁드립니다.
강연욱 - rokkyw@khu.ac.kr
강연욱 - rokkyw@khu.ac.kr / rokkyw@naver.com
......
......@@ -8,6 +8,7 @@ import bodyParser from "body-parser";
import passport from "passport";
import mongoose from "mongoose";
import session from "express-session";
import flash from "express-flash";
import MongoStore from "connect-mongo";
import { localsMiddleware } from "./middlewares";
import routes from "./routes";
......@@ -39,7 +40,7 @@ app.use(
store: new CokieStore({ mongooseConnection: mongoose.connection }),
})
);
app.use(flash());
app.use(passport.initialize());
app.use(passport.session());
......
@keyframes flashAnimation {
0% {
transform: translateY(-70px);
}
5% {
transform: translateY(0px);
}
95% {
transform: translateY(0px);
}
100% {
transform: translateY(-70px);
}
}
.flash-message__container {
position: fixed;
top: 0;
left: 0;
width: 100%;
padding: 20px;
text-align: center;
animation: flashAnimation 5s ease-in-out forwards;
&.error {
background-color: #e74c3c;
}
&.success {
background-color: #2ecc71;
}
&.info {
background-color: #f1c40f;
}
.flash-message__text {
color: white;
font-size: 14px;
}
}
......@@ -10,6 +10,7 @@
@import "partials/videoBlock.scss";
@import "partials/videoPlayer.scss";
@import "partials/videoRecorder.scss";
@import "partials/messages.scss";
@import "pages/home.scss";
@import "pages/videoDetail.scss";
......
......@@ -11,6 +11,7 @@ export const postJoin = async (req, res, next) => {
body: { name, email, password, password2 },
} = req;
if (password !== password2) {
req.flash("error", "Passwords don't match");
res.status(400);
res.render("join", { pageTitle: "Join" });
} else {
......@@ -37,10 +38,15 @@ export const getLogin = (req, res) =>
export const postLogin = passport.authenticate("local", {
failureRedirect: routes.login,
successRedirect: routes.home,
successFlash: "Welcome",
failureFlash: "Can't log in. Check email and/or password",
});
// 깃허브 로그인
export const githubLogin = passport.authenticate("github");
export const githubLogin = passport.authenticate("github", {
successFlash: "Welcome",
failureFlash: "Can't log in. Check email and/or password",
});
// call back 받아오는 함수
export const githubLoginCallback = async (
accessToken,
......@@ -78,7 +84,10 @@ export const postGithubLogin = (req, res) => {
res.redirect(routes.home);
};
export const facebookLogin = passport.authenticate("facebook");
export const facebookLogin = passport.authenticate("facebook", {
successFlash: "Welcome",
failureFlash: "Can't log in. Check email and/or password",
});
// http://www.passportjs.org/packages/passport-facebook/ 참고하였습니다.
export const facebookLoginCallback = async (_, __, profile, cb) => {
......@@ -92,7 +101,7 @@ export const facebookLoginCallback = async (_, __, profile, cb) => {
user.avatarUrl = `https://graph.facebook.com/${id}/picture?type=large`;
user.save();
return cb(null, user);
}
} // graph API 참조.
const newUser = await User.create({
email,
name,
......@@ -114,10 +123,11 @@ export const postFacebookLogin = (req, res) => {
// 즉, 초반에 만들어둔 logout.pug는 삭제해도 좋다.
export const logout = (req, res) => {
// res.render("logout", { pageTitle: "Logout" });
req.flash("info", "Logged out, see you later");
req.logout();
res.redirect(routes.home);
};
// 미들웨어로 부터 로그인한 user를 받는다.
export const getMe = async (req, res) => {
try {
const user = await User.findById(req.user.id).populate("videos");
......@@ -137,6 +147,7 @@ export const userDetail = async (req, res) => {
const user = await User.findById(id).populate("videos");
res.render("userDetail", { pageTitle: "User Detail", user });
} catch (error) {
req.flash("error", "User not found");
res.redirect(routes.home);
}
};
......@@ -155,8 +166,10 @@ export const postEditProfile = async (req, res) => {
email,
avatarUrl: file ? file.location : req.user.avatarUrl, // S3 적용때메 file.path -> file.location 변경(06/24)
});
req.flash("success", "Profile updated");
res.redirect(routes.me);
} catch (error) {
req.flash("error", "Can't update profile");
res.redirect(`/users${routes.editProfile}`);
}
};
......@@ -170,6 +183,7 @@ export const postChangePassword = async (req, res) => {
} = req;
try {
if (newPassword !== newPassword1) {
req.flash("error", "Passwords don't match");
res.status(400);
res.redirect(`/users${routes.changePassword}`);
return;
......@@ -177,6 +191,7 @@ export const postChangePassword = async (req, res) => {
await req.user.changePassword(oldPassword, newPassword);
res.redirect(routes.me);
} catch (error) {
req.flash("error", "Can't change password");
res.status(400);
res.redirect(`/users${routes.changePassword}`);
}
......
......@@ -40,11 +40,11 @@ export const postUpload = async (req, res) => {
// 이는 pug와 db.js를 확인해야하는 듯 하다.
const {
body: { title, description },
file: { location }, // path로 할때는 로컬의 경로. S3는 location
file: { path }, // path로 할때는 로컬의 경로. S3는 location
} = req; // file에 path라는 요소가 있다.
const newVideo = await Video.create({
fileUrl: location,
fileUrl: path,
title,
description,
creator: req.user.id,
......@@ -66,6 +66,7 @@ export const videoDetail = async (req, res) => {
const video = await Video.findById(id)
.populate("creator")
.populate("comments");
console.log(video);
res.render("videoDetail", { pageTitle: video.title, video });
} catch (error) {
res.redirect(routes.home);
......
......@@ -4,7 +4,7 @@ import dotenv from "dotenv";
dotenv.config();
mongoose.connect(process.env.MONGO_URL_PROD, {
mongoose.connect(process.env.MONGO_URL, {
useNewUrlParser: true,
useFindAndModify: false,
});
......
......@@ -12,15 +12,17 @@ const s3 = new aws.S3({
region: "ap-northeast-2",
});
// const multerVideo = multer({ dest: "uploads/videos/" });
const multerVideo = multer({ dest: "uploads/videos/" });
/*
const multerVideo = multer({
storage: multerS3({
s3,
acl: "public-read",
bucket: "khutube/video",
}),
});
// const multerAvatar = multer({ dest: "uploads/avatars/" });
});*/
const multerAvatar = multer({ dest: "uploads/avatars/" });
/*
const multerAvatar = multer({
storage: multerS3({
s3,
......@@ -28,11 +30,12 @@ const multerAvatar = multer({
bucket: "khutube/avatars",
}),
});
*/
export const localsMiddleware = (req, res, next) => {
res.locals.siteName = "my Youtube";
res.locals.routes = routes;
res.locals.loggedUser = req.user || null;
// console.log(req);
next();
};
......
......@@ -31,6 +31,7 @@
"css-loader": "^3.5.3",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"express-flash": "0.0.2",
"express-session": "^1.17.1",
"extract-text-webpack-plugin": "^4.0.0-beta.0",
"get-blob-duration": "^1.1.1",
......
......@@ -501,6 +501,91 @@ input[type="submit"] {
width: 100%;
margin-bottom: 20px; }
@-webkit-keyframes flashAnimation {
0% {
-webkit-transform: translateY(-70px);
transform: translateY(-70px); }
5% {
-webkit-transform: translateY(0px);
transform: translateY(0px); }
95% {
-webkit-transform: translateY(0px);
transform: translateY(0px); }
100% {
-webkit-transform: translateY(-70px);
transform: translateY(-70px); } }
@-moz-keyframes flashAnimation {
0% {
-moz-transform: translateY(-70px);
transform: translateY(-70px); }
5% {
-moz-transform: translateY(0px);
transform: translateY(0px); }
95% {
-moz-transform: translateY(0px);
transform: translateY(0px); }
100% {
-moz-transform: translateY(-70px);
transform: translateY(-70px); } }
@-o-keyframes flashAnimation {
0% {
-o-transform: translateY(-70px);
transform: translateY(-70px); }
5% {
-o-transform: translateY(0px);
transform: translateY(0px); }
95% {
-o-transform: translateY(0px);
transform: translateY(0px); }
100% {
-o-transform: translateY(-70px);
transform: translateY(-70px); } }
@keyframes flashAnimation {
0% {
-webkit-transform: translateY(-70px);
-moz-transform: translateY(-70px);
-o-transform: translateY(-70px);
transform: translateY(-70px); }
5% {
-webkit-transform: translateY(0px);
-moz-transform: translateY(0px);
-o-transform: translateY(0px);
transform: translateY(0px); }
95% {
-webkit-transform: translateY(0px);
-moz-transform: translateY(0px);
-o-transform: translateY(0px);
transform: translateY(0px); }
100% {
-webkit-transform: translateY(-70px);
-moz-transform: translateY(-70px);
-o-transform: translateY(-70px);
transform: translateY(-70px); } }
.flash-message__container {
position: fixed;
top: 0;
left: 0;
width: 100%;
padding: 20px;
text-align: center;
-webkit-animation: flashAnimation 5s ease-in-out forwards;
-moz-animation: flashAnimation 5s ease-in-out forwards;
-o-animation: flashAnimation 5s ease-in-out forwards;
animation: flashAnimation 5s ease-in-out forwards; }
.flash-message__container.error {
background-color: #e74c3c; }
.flash-message__container.success {
background-color: #2ecc71; }
.flash-message__container.info {
background-color: #f1c40f; }
.flash-message__container .flash-message__text {
color: white;
font-size: 14px; }
.home-videos {
display: grid;
grid-template-columns: repeat(6, minmax(150px, 1fr));
......
//공통되는 코드가 필요한 경우div
include ../mixins/message
doctype html
html
head
......@@ -7,6 +7,21 @@ html
title #{pageTitle} | #{siteName}
link(rel="stylesheet", href="/static/style.css")
body
if messages.error
+message({
type:'error',
text:messages.error
})
else if messages.info
+message({
type:'info',
text:messages.info
})
else if messages.success
+message({
type:'success',
text:messages.success
})
include ../partials/header
main
block content
......
mixin message(message={})
.flash-message__container(class=message.type)
span.flash-message__text=message.text
mixin videoPlayer(video={})
.videoPlayer#jsVideoPlayer
video(src=video.src)
video(src=`/${video.src}`)
.videoPlayer__controls
.videoPlayer__column
span#jsVolumeBtn
......