Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
140 commits
Select commit Hold shift + click to select a range
4111b32
add proxyquire & sequelize-mock npm lib
AmberYen Oct 12, 2021
161a837
add new A17 test
AmberYen Oct 12, 2021
bb8ce89
tests/A17.test.js added comments
AmberYen Oct 18, 2021
c15fe79
add A19 test
AmberYen Oct 18, 2021
da713e0
add A20 test
AmberYen Oct 18, 2021
88812da
add A21 test
AmberYen Oct 18, 2021
a7d56e1
add A22 test
AmberYen Oct 18, 2021
d4a7391
add commnets for A17
AmberYen Oct 19, 2021
e981eb0
add comments for A19
AmberYen Oct 19, 2021
5396cf6
add comments for A22
AmberYen Oct 19, 2021
dab9f1d
add comments for A21
AmberYen Oct 19, 2021
c7a336d
add comments for A22
AmberYen Oct 19, 2021
a175811
adjust coding style
Carrot7712 Oct 27, 2021
39950b9
修改變數名與註解
Carrot7712 Oct 27, 2021
82de6c8
refactor mock db in unit test / integrated into helpers/unitTestHelpers
AmberYen Oct 28, 2021
c9b201e
remove n_comments check due to follow model answer
AmberYen Oct 28, 2021
50476ab
revise comments
Carrot7712 Oct 28, 2021
b3ddfcd
add A21 test userId and restaurantId with addLike function
AmberYen Oct 29, 2021
6c5f774
add viewCounts check in A20
AmberYen Oct 29, 2021
2ad4b59
add new test comment
AmberYen Oct 29, 2021
a2df6a4
remove other test and rename A17 -> R01
AmberYen Oct 31, 2021
2f9c683
changed all test file name
AmberYen Oct 31, 2021
d3a66dd
remove R03/04/05 test
AmberYen Oct 31, 2021
e0dbcb6
remove R04/05 test
AmberYen Oct 31, 2021
5a83153
remove R05 test
AmberYen Oct 31, 2021
9148715
fixed R01 ../../app issue & not found sequelize lib
AmberYen Nov 1, 2021
154a12e
fixed R01 ../../app issue & not found sequelize lib
AmberYen Nov 1, 2021
c3b664c
fixed R01 ../../app issue & not found sequelize lib
AmberYen Nov 1, 2021
67b9b32
fixed R01 ../../app issue & not found sequelize lib
AmberYen Nov 1, 2021
ba68733
fixed controller path wrong issue / check data exist
AmberYen Nov 1, 2021
3f256dc
fixed controller path wrong issue / check data exist
AmberYen Nov 1, 2021
0ab85cd
fixed wrong path
AmberYen Nov 1, 2021
a342d2d
fixed controller path wrong issue / check data exist
AmberYen Nov 1, 2021
b10ee15
fixed wrong path
AmberYen Nov 1, 2021
28011ed
fixed controller path wrong issue / check data exist
AmberYen Nov 1, 2021
9b8b4b1
fixed wrong path
AmberYen Nov 1, 2021
e45367f
add mockRequest / mockResponse
AmberYen Nov 1, 2021
d487f4a
use new mockRequest / mockResponse
AmberYen Nov 1, 2021
73fc123
require sinon
AmberYen Nov 1, 2021
5224b9a
remove sinon
AmberYen Nov 1, 2021
5d61a30
add mockRequest / mockResponse
AmberYen Nov 1, 2021
51b22d5
use new mockRequest / mockResponse
AmberYen Nov 1, 2021
eba6e76
require sinon
AmberYen Nov 1, 2021
70db2a5
remove sinon
AmberYen Nov 1, 2021
94b4d56
remove sinon
AmberYen Nov 1, 2021
2d18631
add mockRequest / mockResponse
AmberYen Nov 1, 2021
a79fdd0
use new mockRequest / mockResponse
AmberYen Nov 1, 2021
7fef8c7
require sinon
AmberYen Nov 1, 2021
c8beeb2
add mockRequest / mockResponse
AmberYen Nov 1, 2021
3a85cde
use new mockRequest / mockResponse
AmberYen Nov 1, 2021
61c6de7
require sinon
AmberYen Nov 1, 2021
8927621
remove sinon
AmberYen Nov 1, 2021
9bf30ca
return [defaulvalue] when findall data empty
AmberYen Nov 1, 2021
05b87a2
remove done param
AmberYen Nov 2, 2021
c014106
remove done param
AmberYen Nov 2, 2021
6eecc8a
remove done param
AmberYen Nov 2, 2021
a04125f
remove done param
AmberYen Nov 2, 2021
a1cf9c3
update readme config.json package.json
Carrot7712 Nov 3, 2021
5e1573a
Update .travis.yml
Carrot7712 Nov 5, 2021
c71da44
Update .travis.yml
Carrot7712 Nov 5, 2021
1da8f64
R02 use new mockRequest / mockResponse
AmberYen Nov 1, 2021
dcc8f0e
add helper ref
AmberYen Nov 7, 2021
6799804
remove mockRequest, mockResponse
AmberYen Nov 7, 2021
d54a7fd
R02 use new mockRequest / mockResponse
AmberYen Nov 1, 2021
dde5d1d
add helper ref
AmberYen Nov 7, 2021
ec34393
R02 use new mockRequest / mockResponse
AmberYen Nov 1, 2021
8b395b2
add helper ref
AmberYen Nov 7, 2021
049790e
use new mockRequest, mockResponse
AmberYen Nov 7, 2021
a9d4082
use new mockRequest, mockResponse
AmberYen Nov 7, 2021
72b9738
update readme config.json package.json
Carrot7712 Nov 3, 2021
8c88719
Update .travis.yml
Carrot7712 Nov 5, 2021
ec2c6df
Update .travis.yml
Carrot7712 Nov 5, 2021
80d4dd1
update readme config.json package.json
Carrot7712 Nov 3, 2021
7dc7a56
Update .travis.yml
Carrot7712 Nov 5, 2021
88575da
Update .travis.yml
Carrot7712 Nov 5, 2021
dd4522b
update readme config.json package.json
Carrot7712 Nov 3, 2021
894675f
Update .travis.yml
Carrot7712 Nov 5, 2021
da3a406
Update .travis.yml
Carrot7712 Nov 5, 2021
29dd825
Update config.json
Carrot7712 Nov 8, 2021
20cab63
Update config.json
Carrot7712 Nov 8, 2021
844162a
Update config.json
Carrot7712 Nov 8, 2021
32a6374
Update config.json
Carrot7712 Nov 8, 2021
9300404
Initialize project
area268457913 Nov 8, 2021
28f8ed5
add restaurant index page
area268457913 Nov 8, 2021
b0d4dcf
add admin restaurant indexpage
area268457913 Nov 9, 2021
19e21be
Initialize sequelize and connect to database
area268457913 Nov 9, 2021
347a81e
Create user model
area268457913 Nov 9, 2021
6da840a
Install bcryptjs & Add userController and signup page & Install body-…
area268457913 Nov 9, 2021
083555d
Install bcryptjs & Add userController and signup page & Install body-…
area268457913 Nov 9, 2021
b83c195
Install express-session connect-flash & Confirm user password and uni…
area268457913 Nov 9, 2021
fad1ca4
Install passport and passport-local & Add feature: signInPage, signIn…
area268457913 Nov 9, 2021
e315016
Add navbar to show login status
area268457913 Nov 9, 2021
a9708ec
Add isAdmin to users table & Add authentication before rendering pages
area268457913 Nov 10, 2021
06d07af
Create restaurant model
area268457913 Nov 10, 2021
3328880
Add admin restaurant index page
area268457913 Nov 10, 2021
9ed480e
Add admin restaurant create form & Add admin restaurant post feature
area268457913 Nov 10, 2021
7fd8fff
Add admin restaurant page
area268457913 Nov 10, 2021
30a4f64
Update admin create page for editing usage & Install method-override …
area268457913 Nov 10, 2021
a5fb3f3
Add admin restaurant delete feature
area268457913 Nov 10, 2021
a423fc6
Add image to restaurants & Install multer and add image upload feature
area268457913 Nov 11, 2021
9500c87
Add user seed data & Install faker and add restaurant seed data
area268457913 Nov 11, 2021
91bd4f8
Install pg and update production config
area268457913 Nov 12, 2021
51d9794
updata port & add Procfile
area268457913 Nov 12, 2021
16306d3
Install Imgur api and update admin POST and PUT & Add dotenv
area268457913 Nov 12, 2021
67ebf54
heroku PG switch to ClearDB mysql
area268457913 Nov 12, 2021
45ccbf0
...
area268457913 Nov 12, 2021
a43c2d9
[Assignment Preparation] ensureAuthenticated & getUser
area268457913 Nov 12, 2021
14a4d4d
adminController.getUser & adminController.toggleAdmin
area268457913 Nov 13, 2021
ac321f9
...
area268457913 Nov 14, 2021
0503e53
...
area268457913 Nov 14, 2021
390e073
Create category model & Add restaurant.CategoryId and association
area268457913 Nov 15, 2021
5e8775e
Add category seed data
area268457913 Nov 15, 2021
a984021
Show category name on admin/restaurants & Show category name on admin…
area268457913 Nov 15, 2021
6689280
Add categories selector on admin create and edit page & Add selected …
area268457913 Nov 16, 2021
cec4721
Update category select in edit page using ifCond-helper
area268457913 Nov 16, 2021
bee35a6
Add admin categories page
area268457913 Nov 16, 2021
b86876a
Add admin categories post feature
area268457913 Nov 16, 2021
f546890
Add admin categories edit and put feature
area268457913 Nov 16, 2021
bce9c34
Add admin categories delete feature
area268457913 Nov 16, 2021
5480a39
Add restaurants index page
area268457913 Nov 16, 2021
b23ab88
Add restaurants show page
area268457913 Nov 17, 2021
1fdff67
Add categories navbar on restaurants index page
area268457913 Nov 17, 2021
959fffa
Add pagination on restaurants index
area268457913 Nov 17, 2021
16e160e
Create comment model & add association among users, comment, restaurants
area268457913 Nov 17, 2021
7b9cd24
Add post comment feature on restaurant page
area268457913 Nov 17, 2021
0f516e6
Show related comments on restaurant page & Convert time format using …
area268457913 Nov 17, 2021
0bb3455
Add delete comment feature for admin
area268457913 Nov 17, 2021
fa1a629
fix conflict
area268457913 Nov 18, 2021
5b37329
create profile page
area268457913 Nov 20, 2021
db4e0b9
add update profile & seed
area268457913 Nov 20, 2021
4e10070
update editUser
area268457913 Nov 20, 2021
45211ea
Add feeds page & Update getFeeds to Promise.all
area268457913 Nov 20, 2021
bd4b9c0
fix conflict
area268457913 Nov 20, 2021
8f6d20c
add Dashboard page
area268457913 Nov 20, 2021
af36df3
add viewCounts
area268457913 Nov 21, 2021
2c56bc2
Create favorite model and set association between restaurant and user
area268457913 Nov 21, 2021
5b4965f
Switch add/remove favorite button on restaurants index page & Add add…
area268457913 Nov 21, 2021
3a46c1f
fix conflict
area268457913 Nov 21, 2021
b352f5b
add Like & Unlike
area268457913 Nov 21, 2021
e8116c4
Merge branch 'main' into R04
area268457913 Nov 21, 2021
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
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
IMGUR_CLIENT_ID=SKIP
1 change: 1 addition & 0 deletions Procfile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
web: NODE_ENV=production node app.js
6 changes: 3 additions & 3 deletions _helpers.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
function ensureAuthenticated(req) {
return req.isAuthenticated();
return req.isAuthenticated()
}

function getUser(req) {
return req.user;
return req.user
}

module.exports = {
ensureAuthenticated,
getUser,
};
}
44 changes: 42 additions & 2 deletions app.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,51 @@
const express = require('express')
const handlebars = require('express-handlebars') // 引入 handlebars
const bodyParser = require('body-parser')// Express 升級到了 4.17.1 之後,不用額外載入 body-parser,這行程式碼便不用寫
const flash = require('connect-flash')
const helpers = require('./_helpers')
if (process.env.NODE_ENV !== 'production') {
require('dotenv').config()
}

const session = require('express-session')
const passport = require('./config/passport')
const methodOverride = require('method-override')

const db = require('./models') // 引入資料庫
const app = express()
const port = 3000
const port = process.env.PORT || 3000


app.engine('handlebars', handlebars({
defaultLayout: 'main',
helpers: require('./config/handlebars-helpers')
})) // Handlebars 註冊樣板引擎
app.set('view engine', 'handlebars') // 設定使用 Handlebars 做為樣板引擎
app.use(express.urlencoded({ extended: true }))

app.use(session({ secret: 'secret', resave: false, saveUninitialized: false }))
app.use(passport.initialize())
app.use(passport.session())
app.use(flash())

// 把 req.flash 放到 res.locals 裡面
app.use((req, res, next) => {
res.locals.success_messages = req.flash('success_messages')
res.locals.error_messages = req.flash('error_messages')
//res.locals.user = req.user //讓views能存取user
res.locals.user = helpers.getUser(req) // 取代 req.user
next()
})

app.use(methodOverride('_method'))
app.use('/upload', express.static(__dirname + '/upload'))


app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})
// 引入 routes 並將 app 傳進去,讓 routes 可以用 app 這個物件來指定路由

require('./routes')(app)
require('./routes')(app, passport)

module.exports = app
8 changes: 2 additions & 6 deletions config/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,7 @@
"dialect": "mysql"
},
"production": {
"username": "root",
"password": null,
"database": "database_production",
"host": "127.0.0.1",
"dialect": "mysql"
"use_env_variable": "CLEARDB_DATABASE_URL"
},
"travis": {
"username": "travis",
Expand All @@ -20,4 +16,4 @@
"dialect": "mysql",
"logging": false
}
}
}
14 changes: 14 additions & 0 deletions config/handlebars-helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const moment = require('moment')


module.exports = {
ifCond: function (a, b, options) {
if (a === b) {
return options.fn(this)
}
return options.inverse(this)
},
moment: function (a) {
return moment(a).fromNow()
}
}
45 changes: 45 additions & 0 deletions config/passport.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
const passport = require('passport')
const LocalStrategy = require('passport-local')
const bcrypt = require('bcryptjs')
const db = require('../models')
const User = db.User
const Restaurant = db.Restaurant



// setup passport strategy
passport.use(new LocalStrategy(
// customize user field
{
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true
},
// authenticate user
(req, username, password, cb) => {
User.findOne({ where: { email: username } }).then(user => {
if (!user) return cb(null, false, req.flash('error_messages', '帳號或密碼輸入錯誤'))
if (!bcrypt.compareSync(password, user.password)) return cb(null, false, req.flash('error_messages', '帳號或密碼輸入錯誤!'))
return cb(null, user)
})
}
))

// serialize and deserialize user
passport.serializeUser((user, cb) => {
cb(null, user.id)
})
passport.deserializeUser((id, cb) => {
User.findByPk(id, {
include: [
{ model: Restaurant, as: 'FavoritedRestaurants' },
{ model: Restaurant, as: 'LikeRestaurants' }

]
}).then(user => {
user = user.toJSON()
return cb(null, user)
})
})

module.exports = passport
183 changes: 183 additions & 0 deletions controllers/adminController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
const db = require('../models')
const Restaurant = db.Restaurant
const fs = require('fs')
const imgur = require('imgur-node-api')
const category = require('../models/category')
const IMGUR_CLIENT_ID = process.env.IMGUR_CLIENT_ID
const User = db.User
const Category = db.Category


const adminController = {
getRestaurants: (req, res) => {
return Restaurant.findAll({
raw: true,
nest: true,
include: [Category]
}).then(restaurants => {
// console.log(restaurants)
return res.render('admin/restaurants', { restaurants: restaurants })
})
},

createRestaurant: (req, res) => {
Category.findAll({
raw: true,
nest: true
}).then(categories => {
return res.render('admin/create', {
categories: categories
})
})
},

postRestaurant: (req, res) => {
if (!req.body.name) {
req.flash('error_messages', "name didn't exist")
return res.redirect('back')
}

const { file } = req
if (file) {
imgur.setClientID(IMGUR_CLIENT_ID);
imgur.upload(file.path, (err, img) => {
return Restaurant.create({
name: req.body.name,
tel: req.body.tel,
address: req.body.address,
opening_hours: req.body.opening_hours,
description: req.body.description,
image: file ? img.data.link : null,
CategoryId: req.body.categoryId

}).then((restaurant) => {
req.flash('success_messages', 'restaurant was successfully created')
return res.redirect('/admin/restaurants')
})
})
}
else {
return Restaurant.create({
name: req.body.name,
tel: req.body.tel,
address: req.body.address,
opening_hours: req.body.opening_hours,
description: req.body.description,
image: null,
CategoryId: req.body.categoryId

}).then((restaurant) => {
req.flash('success_messages', 'restaurant was successfully created')
return res.redirect('/admin/restaurants')
})
}
},
getRestaurant: (req, res) => {
return Restaurant.findByPk(req.params.id, { include: [Category] }).then(
restaurant => {
console.log(restaurant)
return res.render('admin/restaurant', {
restaurant: restaurant.toJSON()
})
}
)
},

editRestaurant: (req, res) => {
Category.findAll({
raw: true,
nest: true
}).then(categories => {
return Restaurant.findByPk(req.params.id).then(restaurant => {
return res.render('admin/create', {
categories: categories,
restaurant: restaurant.toJSON()
})
})

})
},

putRestaurant: (req, res) => {
if (!req.body.name) {
req.flash('error_messages', "name didn't exist")
return res.redirect('back')
}

const { file } = req
if (file) {
imgur.setClientID(IMGUR_CLIENT_ID);
imgur.upload(file.path, (err, img) => {
return Restaurant.findByPk(req.params.id)
.then((restaurant) => {
restaurant.update({
name: req.body.name,
tel: req.body.tel,
address: req.body.address,
opening_hours: req.body.opening_hours,
description: req.body.description,
image: file ? img.data.link : restaurant.image,
CategoryId: req.body.categoryId

})
.then((restaurant) => {
req.flash('success_messages', 'restaurant was successfully to update')
res.redirect('/admin/restaurants')
})
})
})
}
else {
return Restaurant.findByPk(req.params.id)
.then((restaurant) => {
restaurant.update({
name: req.body.name,
tel: req.body.tel,
address: req.body.address,
opening_hours: req.body.opening_hours,
description: req.body.description,
image: restaurant.image,
CategoryId: req.body.categoryId

})
.then((restaurant) => {
req.flash('success_messages', 'restaurant was successfully to update')
res.redirect('/admin/restaurants')
})
})
}
},

deleteRestaurant: (req, res) => {
return Restaurant.findByPk(req.params.id)
.then((restaurant) => {
restaurant.destroy()
.then((restaurant) => {
res.redirect('/admin/restaurants')
})
})
},

getUsers: (req, res) => {
return User.findAll({ raw: true }).then(users => {
return res.render('admin/users', { users: users })
})

},
toggleAdmin: (req, res) => {
return User.findByPk(req.params.id).then((user) => {
const { isAdmin, email } = user.toJSON();
if (email === "root@example.com") {
req.flash("error_messages", "禁止變更管理者權限");
return res.redirect("back");
} else {
user.update({ isAdmin: !isAdmin }).then((user) => {
req.flash("success_messages", "使用者權限變更成功");
res.redirect("/admin/users");
});
}
});
},
}

module.exports = adminController
Loading