認證功能-設定錄由、創造註冊

AC課程,學習如何撰寫登入功能。

使用者故事

  1. 使用者可以在註冊頁面輸入名字。
  2. 使用者成功註冊後,可以再登入頁面透過 email 、密碼登入。
  3. 使用者成功登入後,可以看到屬於自己的資訊頁面。
  4. 使用者可以登出,登出後回到登入頁面。

註冊畫面(註冊失敗回到畫面,顯示提示) → 註冊/登入 成功到達主頁 ←→ 登入頁面(登入失敗顯示提示,登出回到登入頁面)

頁面設計
|頁面|網址|
|—|—|
|登入頁面|www.example.com/users/login|
|註冊頁面|www.example.com/users/register|
|登出|www.example.com/users/logout|

設定路由 (router/user.js)

  • 將路由需要用的的檔案全部開出來
  • 設定畫面
  • 串聯邏輯

總共設置五組路由

功能 Http request
瀏覽登入頁面 GET
登入 POST
瀏覽註冊頁面 GET
註冊 POST
登出 GET
const express =require('express')
const router = express.Router()

// 登入
router.get('/login', (req, res) => {
res.render('login')
})
// 送出檢查
router.post('/login', (req, res) => {
res.render('login')
// 註冊
router.get('/register', (req, res) => {
res.render('register')
})
// 送出註冊
router.post('/register', (req, res) => {
res.render('register')
})
// 登出
router.get('/logout', (req, res) => {
res.send('logout')
})
module.exports = router

app.js 中,將剛剛新增的路由引入,放置在 app.use('/todos',require('./routers/todo') 下面

app.use('/users', require('./routers/user.js'))

設定前端登入/註冊頁面

使用 <form> 中的 action and method 設置資料傳送, label for 綁定 input id

user model

創造在 model 資料夾中

編輯用來儲存使用者資料規格的檔案,需要先定義 schema

步驟為

  • 新增 user model
  • app.js 載入 user model

希望格式

屬性 描述 資料型別
name username 字串
email 用email登入不可重複 字串
password 使用這密碼 字串
date 註冊日期 日期

models/user.js 編輯需要格式

// 引入 mongoose , 創造Schema
const mongoose = require('mongoose')
const Schema = mongoose.Schema
const userSchema = new Schema({
name: {
typr: String,
required: true,
},
email: {
typr: String,
required: true,
},
password: {
typr: String,
required: true,
},
date: {
typr: Date,
default: Date.now
},
})
module.exports = mongoose.model('User', userSchema) //User 在資料庫會自動成為 user collection

修改 routers/user.js 引入 models/user.js

const express = require('express')
const router = express.Router()
const User = require('../models/user.js')

註冊功能

  1. 處理註冊頁面傳過來的請求
  2. 檢查使用者是否註冊過
  3. 新使用者,在 使用者資料庫(user database) 新增資料,將使用者帶到專屬頁面

處理請求

更新路由與controller,處理註冊頁面的請求(request) ,使用name、email、password、password2

修改註冊路由,在 router/user.js , 使用解構賦值(Object Desturcturing Assignment)

// 送出註冊
router.post('/register', (req, res) => {
const {name, email, password, password2} = req.body
})

Desturcturing 可以將陣列或物件中指定資料取出變成變數,邏輯與下面相同。

const name = req.body.name
const email = req.body.email
const password = req.body.password
const password2 = req.body.password2

檢查是否註冊

使用 findOne 方法跟 email 做為檢查,尋找在 user model 是否相符合,而一個帳號只有一個 email 所以用 findOne。

使用 ES6 Promise 語法工具 then,為非同步程式設計工具,減少資料等待時間,如果資料沒有錯誤就繼續執行 then callback 動作,如果使用者註冊了重新渲染註冊頁面,回傳資料表單。

如果沒有註冊,在資料庫新增使用者資料。

// 送出註冊
router.post('/register', (req, res) => {
const {name, email, password, password2} = req.body

User.findOne({email:email}).then(user => {
if (user) { // exist or not
console.log('User already exists')
res.render('register',{ // already exists
name,
email,
password,
password2,
})
} else { // if user's email doesn't exist
const newUser = new User({ // create a new user data
name,
email,
password,
password2
})
newUser
.save() // save data
.then(user => {
res.redirect('/') // 將新增傳入資料庫,並回到首頁
})
.catch(err => console.log(err)) // 如果save失敗就用 catch 接住
}
})
})