186 lines
8.0 KiB
JavaScript
186 lines
8.0 KiB
JavaScript
const User = require("../models/mongooseSchemas/User");
|
||
|
||
const router = require("express").Router();
|
||
const passport = require("passport");
|
||
const dataRender = require("../models/DataRender");
|
||
|
||
const fieldLastName_Validator = /^[a-zA-Z\u2E80-\u2FDF\u3190-\u319F\u3400-\u4DBF\u4E00-\u9FFF\uF900-\uFAFF]{1,16}$/;
|
||
const fieldFirstName_Validator = /^([a-zA-Z\u2E80-\u2FDF\u3190-\u319F\u3400-\u4DBF\u4E00-\u9FFF\uF900-\uFAFF]{1,16})([\ ]*)([a-zA-Z]{0,16})$/;
|
||
const fieldEmail_Validator = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
||
const fieldUsername_Validator = /^([a-zA-z]{1,1})([0-9a-zA-z]{3,15})$/;
|
||
const fieldPassword_Validator = /(^[0-9a-zA-Z_?!@#+-]{5,16}$)/;
|
||
|
||
/**
|
||
* 頁面「註冊」的路由處理。
|
||
*/
|
||
router.get("/signup", (req, res) => {
|
||
dataRender.DataRender("signup", req.url, req.session, (err, dataObj) => {
|
||
if (err) {
|
||
res.setHeader("Content-Type", "text/plain");
|
||
res.status(500);
|
||
res.end("Server side error : 500\n" + err);
|
||
}
|
||
else {
|
||
res.render("signup", dataObj);
|
||
}
|
||
});
|
||
});
|
||
|
||
/**
|
||
* * 需要為「註冊驗證」另外寫一個Typescript、Javascript模組 *
|
||
* 在「註冊」頁面下,使用者傳回註冊訊息。
|
||
*/
|
||
router.post("/newmembersignup", (req, res) => {
|
||
req.checkBody("lastName") // 檢查「姓」欄位
|
||
.notEmpty()
|
||
.withMessage("「姓」為必要輸入的欄位,請輸入您的大名。")
|
||
.matches(fieldLastName_Validator)
|
||
.withMessage("「姓」欄位輸入錯誤,請輸入小於17字的英文或中文字。");
|
||
|
||
req.checkBody("firstName") // 檢查「名」欄位
|
||
.notEmpty()
|
||
.withMessage("「名」為必要輸入的欄位,請輸入您的大名。")
|
||
.matches(fieldFirstName_Validator)
|
||
.withMessage("「名」欄位輸入錯誤,請輸入小於33字的英文或中文字。");
|
||
|
||
req.checkBody("email") // 檢查「Email」欄位
|
||
.notEmpty()
|
||
.withMessage("\"Email\"為必要輸入的欄位,請輸入您的信箱地址。")
|
||
.matches(fieldEmail_Validator)
|
||
.withMessage("請在\"Email\"欄位中輸入正確的格式。");
|
||
|
||
req.checkBody("username") // 檢查「使用者名稱」欄位
|
||
.notEmpty()
|
||
.withMessage("\"Username\"為必要輸入的欄位,請輸入您想要的帳號名稱。")
|
||
.custom((value) => !/^[0-9]$/.test(value.substr(1,1)))
|
||
.withMessage("\"Username\"欄位中的第一字僅能為英文字母。")
|
||
.matches(fieldUsername_Validator)
|
||
.withMessage("「姓」欄位輸入錯誤,請輸入小於17字的英文或中文字。");
|
||
|
||
req.checkBody("password") // 檢查「密碼」欄位
|
||
.notEmpty()
|
||
.withMessage("\"Password\"為必要輸入的欄位,請輸入您想要的密碼。")
|
||
.matches(fieldPassword_Validator)
|
||
.withMessage("\"Password\"欄位中必須輸入數字、英文字母或「_?!@#+-」中任一字元。");
|
||
|
||
req.checkBody("confirmPassword") // 檢查「確認密碼」欄位
|
||
.notEmpty()
|
||
.withMessage("\"Confirm Password\"為必要輸入的欄位,請再次\"Password\"欄位中的密碼。")
|
||
.equals(req.body.password)
|
||
.withMessage("請在\"Confirm Password\"欄位中輸入與\"Password\"欄位中相符的密碼。");
|
||
|
||
req.checkBody("termsAgreement")
|
||
.isBoolean()
|
||
.withMessage("請勾選表示同意「JMuseum 條款」。")
|
||
.equals("true")
|
||
.withMessage("請勾選表示同意「JMuseum 條款」。");
|
||
|
||
// 取得檢查結果
|
||
req.getValidationResult().then((result) => {
|
||
let errors = result.mapped();
|
||
let responseMsg = {isOK: result.isEmpty()};
|
||
res.setHeader("Content-Type", "application/json");
|
||
// 若檢查通過
|
||
if (responseMsg.isOK) {
|
||
let newUserDataSet = {lastName: req.body.lastName, firstName: req.body.firstName,
|
||
email: req.body.email, username: req.body.username,
|
||
password: req.body.password};
|
||
// 以 newUserDataSet 在資料庫中的User資料表新增使用者資料
|
||
User.createNewUser(newUserDataSet, (err, userDocu) => {
|
||
if (!err) {
|
||
req.session.isNewUser = true; // 在session上標記是一位新使用者
|
||
responseMsg.redirect = "/signupmsg"; // 將轉跳頁面網址加入到回應物件的redirect屬性
|
||
console.log("POST /newmembersignup : A new member " + req.body.username + " signed up successfully.");
|
||
}
|
||
else {
|
||
responseMsg.isOK = false;
|
||
if (User.IsExistSameUsername(err)) {
|
||
responseMsg.field = "username";
|
||
responseMsg.message = "已有人註冊相同的使用者名稱,請更換新的名稱。";
|
||
console.log("POST /newmembersignup : Exist same username.");
|
||
}
|
||
else if (User.IsExistSameEmail(err)) {
|
||
responseMsg.field = "email";
|
||
responseMsg.message = "已有人註冊相同的Email,請更換新的電子信箱。";
|
||
console.log("POST /newmembersignup : Exist same email.");
|
||
}
|
||
else {
|
||
responseMsg.field = "SERVER";
|
||
responseMsg.message = "很抱歉!伺服端處理時發生錯誤,請稍候重試!";
|
||
console.log("POST /newmembersignup - ERROR: " + err);
|
||
}
|
||
}
|
||
res.send(responseMsg);
|
||
});
|
||
}
|
||
else {
|
||
let firstErr = Object.values(errors)[0]; // 取得第一個錯誤訊息物件
|
||
responseMsg.field = firstErr.param; // 將錯誤的欄位名稱新增到回應物件的field屬性
|
||
responseMsg.message = firstErr.msg; // 將錯誤訊息新增到回應物件的message屬性
|
||
res.send(responseMsg);
|
||
console.log("POST /newmembersignup : Have Problem!");
|
||
}
|
||
});
|
||
});
|
||
|
||
/**
|
||
* 在「註冊」成功之後的轉跳訊息頁面。
|
||
*/
|
||
router.get("/signupmsg", (req, res) => {
|
||
// 判斷該訪客是否為剛登入的新使用者
|
||
if (req.session.isNewUser) {
|
||
delete req.session.isNewUser; // 移除isNewUser屬性,避免重複判斷
|
||
dataRender.DataRender("message_form", req.url, req.session, (err, dataObj) => {
|
||
if (err) {
|
||
res.setHeader("Content-Type", "text/plain");
|
||
res.status(500);
|
||
res.end("Server side error : 500\n" + err);
|
||
}
|
||
else {
|
||
res.render("message_form", dataObj);
|
||
}
|
||
});
|
||
}
|
||
// 若不是,則跳轉到首頁。
|
||
else {
|
||
res.redirect("/");
|
||
}
|
||
});
|
||
|
||
/**
|
||
* 頁面「登入」的路由處理。
|
||
*/
|
||
router.get("/login", (req, res) => {
|
||
dataRender.DataRender("login", req.url, req.session, (err, dataObj) => {
|
||
if (err) {
|
||
res.setHeader("Content-Type", "text/plain");
|
||
res.status(500);
|
||
res.end("Server side error : 500\n" + err);
|
||
}
|
||
else {
|
||
let errors = req.flash("error");
|
||
if (errors.length > 0) {
|
||
dataObj.datas.isLoginFailed = true;
|
||
dataObj.datas.loginMessage = errors[0];
|
||
}
|
||
res.render("login", dataObj);
|
||
}
|
||
});
|
||
});
|
||
|
||
/**
|
||
* 在「登入」頁面下,處理、驗證使用者所傳的帳號、密碼是否正確。
|
||
*/
|
||
router.post("/login", passport.authenticate("login", {failureRedirect: "/login", failureFlash: true }), (req, res) => {
|
||
res.redirect("/");
|
||
});
|
||
|
||
/**
|
||
* 客戶端發送「登出」動作,處理後重新導向。
|
||
*/
|
||
router.get("/signout", (req, res) => {
|
||
req.logout();
|
||
res.redirect("/index");
|
||
});
|
||
|
||
module.exports = router; |