Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conform to test c #866

Open
wants to merge 46 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
6b4b881
feat: create user seedes
TCY1020 Aug 20, 2023
e97714a
feat: user & admin sigin, error-handler
TCY1020 Aug 20, 2023
66a795a
Merge pull request #1 from susu725/develop
susu725 Aug 20, 2023
4d05ad4
feat: add tweets seed
susu725 Aug 20, 2023
c48fb19
windows problem
susu725 Aug 20, 2023
f484c42
Merge pull request #2 from susu725/tweets-seed
TCY1020 Aug 20, 2023
5febf38
fix: windows problem
susu725 Aug 20, 2023
3e94119
feat: add replies seed
susu725 Aug 20, 2023
9d36ce6
Merge pull request #3 from susu725/replies-seed
TCY1020 Aug 21, 2023
7988a02
feat: create auth
TCY1020 Aug 21, 2023
37b2655
Merge branch 'authenticator'
TCY1020 Aug 21, 2023
3c8d477
fix: restore migrations to original
susu725 Aug 21, 2023
b3c19b6
fix: modify seeders field name
susu725 Aug 21, 2023
36858e8
feat: add getTweets function
susu725 Aug 21, 2023
e9460f5
feat: add getTweet function
susu725 Aug 21, 2023
46f5728
refactor: modify tweets seed
susu725 Aug 21, 2023
52a68bb
feat: add postTweet function
susu725 Aug 21, 2023
6f3b942
Merge remote-tracking branch 'origin/master' into tweets-function
susu725 Aug 21, 2023
0f908dc
fix: modify seeders field name
susu725 Aug 21, 2023
625ef04
Merge pull request #5 from susu725/tweets-function
TCY1020 Aug 21, 2023
ed95c57
feat: add getReplies function
susu725 Aug 21, 2023
f02ec05
feat: passport & auth, adminGetUser
TCY1020 Aug 21, 2023
b178bf9
Merge branch 'master' of https://github.com/susu725/twitter-api-2020
TCY1020 Aug 21, 2023
1d24688
Merge branch 'adminGetUser'
TCY1020 Aug 21, 2023
ec81bfe
style: white-space
TCY1020 Aug 21, 2023
3e12b4f
feat: reqUser has data
TCY1020 Aug 21, 2023
e5d150e
Merge pull request #6 from susu725/adminGetUser
susu725 Aug 21, 2023
cf1a0d0
Merge pull request #7 from susu725/reqUser
susu725 Aug 21, 2023
bf90b17
feat: add postReply function
susu725 Aug 21, 2023
b23c75a
Merge remote-tracking branch 'origin/master' into replies-function
susu725 Aug 21, 2023
adecc09
Merge pull request #8 from susu725/replies-function
TCY1020 Aug 21, 2023
6b28e4c
feat: add users banner Column
TCY1020 Aug 22, 2023
8e657b1
Merge branch 'addUserColumn'
TCY1020 Aug 22, 2023
be5ac83
feat: adminGetUsers
TCY1020 Aug 22, 2023
4e28213
Merge branch 'adminGetAdminTweets'
TCY1020 Aug 22, 2023
5ca9c6e
Merge pull request #10 from susu725/adminGetAdminTweets
susu725 Aug 22, 2023
4fac80c
fix: getUsers & getAdminTweets
TCY1020 Aug 22, 2023
0b4f2aa
:feat: admin deleteTweet
TCY1020 Aug 22, 2023
3890554
Merge branch 'master' of https://github.com/susu725/twitter-api-2020
TCY1020 Aug 22, 2023
55debc7
Merge branch 'adminDeleteTweet'
TCY1020 Aug 22, 2023
8749659
feat: modify config for heroku
susu725 Aug 22, 2023
7f35feb
style: white-space
TCY1020 Aug 22, 2023
e94e08a
Merge branch 'master' of https://github.com/susu725/twitter-api-2020
TCY1020 Aug 22, 2023
2ceed1a
Merge branch 'master' into adminDeleteTweet
TCY1020 Aug 22, 2023
6e82095
Merge pull request #15 from susu725/adminDeleteTweet
susu725 Aug 22, 2023
d3754ef
fix: user model
TCY1020 Aug 22, 2023
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
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
DB_PASS =
PORT =
JWT_SECRET =
32 changes: 32 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
module.exports = {
env: {
browser: true,
es2021: true
},
extends: [
'standard',
'plugin:react/recommended'
],
overrides: [
{
env: {
node: true
},
files: [
'.eslintrc.{js,cjs}'
],
parserOptions: {
sourceType: 'script'
}
}
],
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module'
},
plugins: [
'react'
],
rules: {
}
}
6 changes: 6 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"cSpell.words": [
"blongs",
"Followship"
]
}
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
9 changes: 4 additions & 5 deletions _helpers.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@

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

module.exports = {
getUser,
};
getUser
}
23 changes: 16 additions & 7 deletions app.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
if (process.env.NODE_ENV !== 'production') {
require('dotenv').config()
}

const express = require('express')
const helpers = require('./_helpers');
const helpers = require('./_helpers')
const routes = require('./routes')

const app = express()
const port = 3000
const port = process.env.PORT || 3000

app.use(express.urlencoded({ extended: true }))
app.use(express.json())

app.use((req, res, next) => {
res.locals.user = helpers.getUser(req)
next()
})

// use helpers.getUser(req) to replace req.user
function authenticated(req, res, next){
// passport.authenticate('jwt', { ses...
};
app.use(routes)

app.get('/', (req, res) => res.send('Hello World!'))
app.listen(port, () => console.log(`Example app listening on port ${port}!`))

module.exports = app
6 changes: 1 addition & 5 deletions config/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,7 @@
"logging": false
},
"production": {
"username": "root",
"password": null,
"database": "database_production",
"host": "127.0.0.1",
"dialect": "mysql"
"use_env_variable": "MYSQL_DATABASE_URL"
},
"travis": {
"username": "travis",
Expand Down
26 changes: 24 additions & 2 deletions config/passport.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,27 @@
const passport = require('passport')
const passportJWT = require('passport-jwt')
const JWTStrategy = passportJWT.Strategy
const ExtractJWT = passportJWT.ExtractJwt
const { User, Tweet } = require('../models')

const jwtOptions = {
jwtFromRequest: ExtractJWT.fromAuthHeaderAsBearerToken(),
secretOrKey: process.env.JWT_SECRET
}
passport.use(new JWTStrategy(jwtOptions, async (jwtPayload, cb) => {
try {
const user = await User.findByPk(jwtPayload.id, {
include: [
Tweet,
{ model: Tweet, as: 'LikeTweets' },
{ model: User, as: 'Followings' },
{ model: User, as: 'Followers' }
]
})
cb(null, user)
} catch (err) {
cb(err)
}
}))


module.exports = passport
module.exports = passport
18 changes: 18 additions & 0 deletions controllers/admin-controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const adminServices = require('../services/admin-services')

const adminController = {
signIn: (req, res, next) => {
adminServices.signIn(req, (err, data) => err ? next(err) : res.status(200).json(data))
},
getUsers: (req, res, next) => {
adminServices.getUsers(req, (err, data) => err ? next(err) : res.status(200).json(data))
},
getAdminTweets: (req, res, next) => {
adminServices.getAdminTweets(req, (err, data) => err ? next(err) : res.status(200).json(data))
},
deleteTweet: (req, res, next) => {
adminServices.deleteTweet(req, (err, data) => err ? next(err) : res.status(200).json(data))
}
}

module.exports = adminController
12 changes: 12 additions & 0 deletions controllers/reply-controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const replyServices = require('../services/reply-services')

const replyController = {
getReplies: (req, res, next) => {
replyServices.getReplies(req, (err, data) => err ? next(err) : res.json({ status: 'success', data }))
},
postReply: (req, res, next) => {
replyServices.postReply(req, (err, data) => err ? next(err) : res.json({ status: 'success', message: '您已成功新增留言', data }))
}
}

module.exports = replyController
15 changes: 15 additions & 0 deletions controllers/tweet-controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const tweetServices = require('../services/tweet-services')

const tweetController = {
getTweets: (req, res, next) => {
tweetServices.getTweets(req, (err, data) => err ? next(err) : res.json({ status: 'success', data }))
},
getTweet: (req, res, next) => {
tweetServices.getTweet(req, (err, data) => err ? next(err) : res.json({ status: 'success', data }))
},
postTweet: (req, res, next) => {
tweetServices.postTweet(req, (err, data) => err ? next(err) : res.json({ status: 'success', data }))
}
}

module.exports = tweetController
12 changes: 12 additions & 0 deletions controllers/user-controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const userServices = require('../services/user-services')

const userController = {
signIn: (req, res, next) => {
userServices.signIn(req, (err, data) => err ? next(err) : res.status(200).json(data))
},
getUser: (req, res, next) => {
userServices.getUser(req, (err, data) => err ? next(err) : res.status(200).json(data))
}
}

module.exports = userController
31 changes: 31 additions & 0 deletions middleware/auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
const passport = require('../config/passport')
const helpers = require('../_helpers')

const authenticated = (req, res, next) => { // 用jwt策略驗證
passport.authenticate('jwt', { session: false }, (err, user) => {
if (err || !user) return res.status(401).json({ status: 'error', message: '沒登入' })
req.user = user // 用cb之後變成req.logIn函式處理所以要自己處理驗證成功時放入req.user
next()
})(req, res, next)
}

const authenticatedAdmin = (req, res, next) => {
if (helpers.getUser(req) && helpers.getUser(req).role === 'admin') {
next()
} else {
return res.status(403).json({ status: 'error', message: '帳號不存在!' })
}
}
const authenticatedUser = (req, res, next) => {
if (helpers.getUser(req) && helpers.getUser(req).role === 'user') {
next()
} else {
return res.status(403).json({ status: 'error', message: '帳號不存在!' })
}
}

module.exports = {
authenticated,
authenticatedAdmin,
authenticatedUser
}
18 changes: 18 additions & 0 deletions middleware/error-handler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const apiErrorHandler = (err, req, res, next) => {
if (err instanceof Error) {
res.status(err.status || 500).json({
status: 'error',
message: `${err.name}: ${err.message}`
})
} else {
res.status(500).json({
status: 'error',
message: `${err}`
})
}
next(err)
}

module.exports = {
apiErrorHandler
}
8 changes: 4 additions & 4 deletions migrations/20190115071418-create-followship.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
'use strict';
'use strict'
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('Followships', {
Expand All @@ -22,9 +22,9 @@ module.exports = {
allowNull: false,
type: Sequelize.DATE
}
});
})
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('Followships');
return queryInterface.dropTable('Followships')
}
};
}
8 changes: 4 additions & 4 deletions migrations/20190115071419-create-like.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
'use strict';
'use strict'
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('Likes', {
Expand All @@ -22,9 +22,9 @@ module.exports = {
allowNull: false,
type: Sequelize.DATE
}
});
})
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('Likes');
return queryInterface.dropTable('Likes')
}
};
}
8 changes: 4 additions & 4 deletions migrations/20190115071420-create-reply.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
'use strict';
'use strict'
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('Replies', {
Expand All @@ -25,9 +25,9 @@ module.exports = {
allowNull: false,
type: Sequelize.DATE
}
});
})
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('Replies');
return queryInterface.dropTable('Replies')
}
};
}
8 changes: 4 additions & 4 deletions migrations/20190115071420-create-tweet.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
'use strict';
'use strict'
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('Tweets', {
Expand All @@ -22,9 +22,9 @@ module.exports = {
allowNull: false,
type: Sequelize.DATE
}
});
})
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('Tweets');
return queryInterface.dropTable('Tweets')
}
};
}
8 changes: 4 additions & 4 deletions migrations/20190115071421-create-user.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
'use strict';
'use strict'
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('Users', {
Expand Down Expand Up @@ -34,9 +34,9 @@ module.exports = {
allowNull: false,
type: Sequelize.DATE
}
});
})
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('Users');
return queryInterface.dropTable('Users')
}
};
}
13 changes: 13 additions & 0 deletions migrations/20230820062110-add-account-to-users.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
'use strict'

module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.addColumn('Users', 'account', {
type: Sequelize.STRING
})
},

down: async (queryInterface, Sequelize) => {
await queryInterface.removeColumn('Users', 'account')
}
}
13 changes: 13 additions & 0 deletions migrations/20230822035000-add-banner-to-users.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
'use strict'

module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.addColumn('Users', 'banner', {
type: Sequelize.STRING
})
},

down: async (queryInterface, Sequelize) => {
await queryInterface.removeColumn('Users', 'banner')
}
}
17 changes: 11 additions & 6 deletions models/followship.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
'use strict';
'use strict'
module.exports = (sequelize, DataTypes) => {
const Followship = sequelize.define('Followship', {
}, {});
Followship.associate = function(models) {
};
return Followship;
};
followerId: DataTypes.INTEGER,
followingId: DataTypes.INTEGER
}, {
modelName: 'Followship',
tableName: 'Followships'
})
Followship.associate = function (models) {
}
return Followship
}
Loading