Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions homeworks/week17/hw1/blog/blog.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
const express = require('express')
const bodyParser = require('body-parser')
const session = require('express-session')
const flash = require('connect-flash');
const blogController = require('./controllers/blog.js')
const userController = require('./controllers/user.js')

const app = express()
const port = 5001

app.set('view engine', 'ejs')
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
app.use(session({
secret: 'keyboard cat',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

這個應該放在環境變數才對,如同 secret 字面上的意思

resave: false,
saveUninitialized: true,
}))
app.use(flash())
app.use(express.static(__dirname + '/public'));

app.use((req, res, next) => {
res.locals.userId = req.session.userId || null;
res.locals.errorMessage = req.flash('errorMessage');
next();
})

app.get('/blog', blogController.init)
app.get('/article/:id', blogController.get)
app.get('/addArticle', blogController.addArticle)
app.get('/admin', blogController.admin)
app.get('/register', userController.register)
app.get('/login', userController.login)
app.get('/logout', userController.logout)
app.get('/update/:id', blogController.updateArticle)
app.get('/delete/:id', blogController.deleteArticle)

app.post('/article', blogController.handleAddArticle)
app.post('/login', userController.handleLogin)
app.post('/register', userController.handleRegister)
app.post('/update/:id', blogController.handleUpdateArticle)

app.listen(port, () => {
console.log(`App listening on port ${port}`)
})
23 changes: 23 additions & 0 deletions homeworks/week17/hw1/blog/config/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"development": {
"username": "root",
"password": "Ss121549!",
"database": "test",
"host": "3.23.99.109",
"dialect": "mysql"
},
"test": {
"username": "root",
"password": null,
"database": "database_test",
"host": "127.0.0.1",
"dialect": "mysql"
},
"production": {
"username": "root",
"password": null,
"database": "database_production",
"host": "127.0.0.1",
"dialect": "mysql"
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

這個檔案要加進 .gitignore 才對

179 changes: 179 additions & 0 deletions homeworks/week17/hw1/blog/controllers/blog.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
const utilis = require('../utilis.js')
const db = require('../models')
const { Op } = require("sequelize");
const User = db.User
const Article = db.Article
const Tag = db.Tags

const blogController = {
init: (req, res) => {
utilis.getUserInfoById(req.session.userId, (user) => {
Article.findAll({
where: {isDeleted: 0},
order:[['id', 'DESC']],
include: User,
include: Tag
}).then(articles => {
res.render('blog', {
user,
articles,
})
}).catch(error => {
console.log(error)
res.redirect('/blog')
})
})
},

admin: (req, res) => {
if(!req.session.userId) return res.redirect('/blog')
utilis.getUserInfoById(req.session.userId, user => {
if(user.authType !== '1') return res.redirect('/blog')
Article.findAll({
where: {isDeleted: 0},
order:[['id', 'DESC']],
include: User
}).then(articles => {
res.render('admin',{
user,
articles,
})
}).catch(error => {
console.log(error)
res.redirect('/blog')
})
})
},

getAll: (req, res) => {
Article.findAll({
where: {isDeleted: 0},
include: User
}).then(articles => {
res.render('blog', {
articles: articles
})
}).catch(error => {
console.log(error)
res.redirect('/blog')
})
},

get: (req, res) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

命名可以更清楚一點,比如說 getArticle,這一部分可以參考其他同學的命名

const id = req.params.id
Article.findByPk(id,{
include: Tag
}).then(article => {
if(!article) {
console.log('Inavlid article Id')
res.redirect('/blog')
return
}
if(article.isDeleted === 1) return res.redirect('/blog')
res.render('readMore', {
user: article.UserId || 0,
article,
})
})
},

addArticle: (req, res) => {
const userId = req.session.userId
if(!userId) return res.redirect('/blog')
utilis.getUserInfoById(userId, user => {
if(user.authType !== '1') {
return res.redirect('/blog')
}
utilis.getAllTags(tags => {
res.render('addArticle', {
user,
tags,
})
})
})
},

handleAddArticle: (req, res) => {
const {title, TagId, content} = req.body
const UserId = req.session.userId
if(!title || !TagId || !content) {
req.flash('errorMessage', '請填入所有欄位')
return res.redirect('/addArticle')
}
Article.create({
UserId,
title,
TagId,
content,
}).then(newArticle => {
res.redirect('/blog')
}).catch(error => {
console.log(error)
req.flash('errorMessage', '新增文章失敗')
return res.redirect('/addArticle')
})
},

updateArticle: (req, res) => {
const userId = req.session.userId
const ArticleId = req.params.id
if(!userId) return res.redirect('/blog')
Article.findByPk(ArticleId, {
include: [User, Tag]
}).then(article => {
if(article.isDeleted === 1) return res.redirect('/blog')
Tag.findAll({
where: {
id: {[Op.ne]:article.TagId}
}
}).then(tags => {
res.render('updateArticle', {
article,
user: article.User,
tags,
})
})
})
},

handleUpdateArticle: (req, res) => {
const ArticleId = req.params.id
const {title, TagId, content} = req.body
if(!title || !TagId || !content) {
req.flash('errorMessage', '請填入所有欄位')
return res.redirect(`/update/${ArticleId}`)
}
Article.update({
title,
TagId,
content,
},{where: {id: ArticleId}}).then(newArticle => {
res.redirect('/blog')
}).catch(error => {
console.log(error)
req.flash('errorMessage', '更新文章失敗')
return res.redirect(`/update/${ArticleId}`)
})
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

可以稍微排版一下,比如說

handleUpdateArticle = (req, res) => {
    const ArticleId = req.params.id
    const { title, TagId, content } = req.body
    if (!title || !TagId || !content) {
        req.flash('errorMessage', '請填入所有欄位')
        return res.redirect(`/update/${ArticleId}`)
    }
    Article.update(
        {
            title,
            TagId,
            content,
        },
        { where: { id: ArticleId } }
    )
        .then((newArticle) => {
            res.redirect('/blog')
        })
        .catch((error) => {
            console.log(error)
            req.flash('errorMessage', '更新文章失敗')
            return res.redirect(`/update/${ArticleId}`)
        })
}


deleteArticle: (req, res) => {
const ArticleId = req.params.id
const sessionUserId = req.session.userId
Article.findByPk(ArticleId).then(article => {
if(article.UserId !== sessionUserId){
return res.redirect('/admin')
}
Article.update({
isDeleted: 1,
},{where: {id: ArticleId}}).then(newArticle => {
res.redirect('/admin')
}).catch(error => {
console.log(error)
req.flash('errorMessage', '刪除文章失敗')
return res.redirect('/admin')
})
})
}
}

module.exports = blogController
82 changes: 82 additions & 0 deletions homeworks/week17/hw1/blog/controllers/user.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
const db = require('../models')
const User = db.User
const Article = db.Article
const bcrypt = require('bcrypt');
const saltRounds = 10;
const myPlaintextPassword = 's0/\/\P4$$w0rD';
const someOtherPlaintextPassword = 'not_bacon';

const userController = {
register: (req, res) => {
res.render('register')
},

handleRegister: (req, res) => {
const {username, password, nickname} = req.body
if(!username || !password || !nickname) {
req.flash('errorMessage', '請填入所有欄位')
res.redirect('/register')
return
}

bcrypt.hash(password, saltRounds, (error, hash) => {
User.create(
{
username,
password: hash,
nickname,
}
).then(user => {
req.session.userId = user.id;
res.redirect('/blog')
}).catch(error => {
req.flash('errorMessage', error)
res.redirect('/register')
})
})
},

login: (req, res) => {
res.render('login')
},

logout: (req,res) => {
req.session.userId = null
res.redirect('/blog')
},

handleLogin: (req, res) => {
const {username, password} = req.body
if(!username || !password) {
req.flash('errorMessage', '請輸入帳號及密碼')
res.redirect('login')
return
}

User.findOne({
where: {
username,
}
}).then(user => {
if(!user) {
req.flash('errorMessage', '請輸入正確帳號及密碼')
res.redirect('login')
return
}
bcrypt.compare(user.password, password.toString(), (error, result) => {
if(error) {
req.flash('errorMessage', '請輸入正確帳號及密碼')
res.redirect('login')
return
}
req.session.userId = user.id;
res.redirect('blog')
});
}).catch(error => {
req.flash('errorMessage', error.Message)
res.redirect('login')
})
}
}

module.exports = userController
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
'use strict';
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.createTable('Articles', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
userId: {
type: Sequelize.INTEGER
},
title: {
type: Sequelize.STRING
},
content: {
type: Sequelize.TEXT
},
tagId: {
type: Sequelize.INTEGER
},
isDeleted: {
type: Sequelize.STRING
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
down: async (queryInterface, Sequelize) => {
await queryInterface.dropTable('Articles');
}
};
Loading