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

前後端分離組:Mi, Paul, Troy, Sunny #922

Open
wants to merge 113 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
113 commits
Select commit Hold shift + click to select a range
52e5a2c
fix eslint error
PoWeiWu Oct 31, 2023
acd7f8c
feat: user model add account and cover
Sunnylin0320 Oct 31, 2023
a0c5bfc
feat: modify models
Sunnylin0320 Oct 31, 2023
86c4714
feat: modify Like Model
Sunnylin0320 Nov 1, 2023
81da6dd
Merge pull request #1 from paulwu-tw/feature/modifyModels
paulwu-tw Nov 1, 2023
51f9e23
feat: user signup
PoWeiWu Nov 1, 2023
83a71e9
Merge branch 'master' into feature/users
PoWeiWu Nov 1, 2023
7a98f68
feat: add users seed
Sunnylin0320 Nov 1, 2023
66d31a2
feat: add tweets seed
Sunnylin0320 Nov 1, 2023
24065b1
feat: add replies seed
Sunnylin0320 Nov 1, 2023
72002c2
Merge remote-tracking branch 'origin' into feature/addSeedData
Sunnylin0320 Nov 1, 2023
76f3ad0
Merge pull request #2 from paulwu-tw/feature/users
paulwu-tw Nov 1, 2023
c8a1e5a
Merge branch 'master' into feature/addSeedData
paulwu-tw Nov 1, 2023
bff6000
Merge pull request #3 from paulwu-tw/feature/addSeedData
paulwu-tw Nov 1, 2023
c945a77
feat: user signIn
PoWeiWu Nov 1, 2023
57fddd7
Merge branch 'master' into feature/users
PoWeiWu Nov 1, 2023
128352b
fix models underscored error
PoWeiWu Nov 1, 2023
008873b
feat: auth middleware
Sunnylin0320 Nov 2, 2023
79b90ed
Merge pull request #5 from paulwu-tw/feature/users
Sunnylin0320 Nov 2, 2023
cc325bb
Merge branch 'master' into feature/middleware/auth
paulwu-tw Nov 2, 2023
d8603ca
Merge pull request #6 from paulwu-tw/feature/middleware/auth
paulwu-tw Nov 2, 2023
7575e60
feat: admin signin
Sunnylin0320 Nov 2, 2023
632164b
Merge pull request #7 from paulwu-tw/feature/adminSignin
paulwu-tw Nov 2, 2023
8eb8c12
feat: auth middleware and followship route
PoWeiWu Nov 2, 2023
7d5e116
Merge branch 'master' into feature/users
PoWeiWu Nov 2, 2023
9a394d1
fix auth problem, and admin-controller error
PoWeiWu Nov 2, 2023
057ecc0
Merge pull request #8 from paulwu-tw/feature/users
Sunnylin0320 Nov 2, 2023
986de1a
feat: admin get users
Sunnylin0320 Nov 2, 2023
996163b
Merge pull request #9 from paulwu-tw/feature/adminGetUsers
paulwu-tw Nov 3, 2023
6f34ffd
feat: admin get tweets
Sunnylin0320 Nov 3, 2023
1867c29
feat: admin delete tweet
Sunnylin0320 Nov 3, 2023
c7675eb
Merge pull request #10 from paulwu-tw/feature/adminGetTweetsAndDelete…
paulwu-tw Nov 3, 2023
80b7179
feat: User get tweets
Sunnylin0320 Nov 3, 2023
6bdad21
feat: User post tweet
Sunnylin0320 Nov 3, 2023
0639d3f
feat: User get tweet
Sunnylin0320 Nov 4, 2023
76ea13e
feat: User add like
Sunnylin0320 Nov 4, 2023
4abb3e9
add Procfile
PoWeiWu Nov 4, 2023
fb0d21a
add heroku procfile
PoWeiWu Nov 4, 2023
fd483c1
feat: User remove like
Sunnylin0320 Nov 4, 2023
99b6105
feat: add day.js
Sunnylin0320 Nov 4, 2023
77132ae
feat: User get Replies
Sunnylin0320 Nov 4, 2023
31203b6
feature: User post reply
Sunnylin0320 Nov 4, 2023
69b087a
add db connection
PoWeiWu Nov 4, 2023
658e6c0
fix db seeds npm module when deploy
PoWeiWu Nov 4, 2023
5c94b02
feat: modify config for heroku
Sunnylin0320 Nov 4, 2023
ac4b353
Merge pull request #11 from paulwu-tw/feature/tweets
paulwu-tw Nov 4, 2023
5e270cf
Merge branch 'master' into feature/users
PoWeiWu Nov 4, 2023
b8fe473
fix db connection when deploy heroku
PoWeiWu Nov 4, 2023
49bc8cf
Merge branch 'feature/users'
PoWeiWu Nov 4, 2023
ae3a1ca
Merge branch master into feature/tweets
Sunnylin0320 Nov 4, 2023
8791b95
Merge pull request #12 from paulwu-tw/feature/users
Sunnylin0320 Nov 4, 2023
05c585b
Merge remote-tracking branch 'origin'
Sunnylin0320 Nov 4, 2023
3e0692c
feat: add cors package for frontend
PoWeiWu Nov 4, 2023
2a7e6cf
feat: edit user proflie
PoWeiWu Nov 4, 2023
628216e
Merge branch 'feature/users'
PoWeiWu Nov 4, 2023
3a318a4
fix: remove image temp file and add .gitignore
PoWeiWu Nov 4, 2023
410e21e
Merge pull request #14 from paulwu-tw/feature/users
Sunnylin0320 Nov 4, 2023
d4bcbea
feat: merge branch 'master' into master
Sunnylin0320 Nov 4, 2023
ece0ec6
feat: getUserTweets route
PoWeiWu Nov 4, 2023
ed0080e
Merge branch 'master' into feature/users
PoWeiWu Nov 4, 2023
acd6837
Merge branch 'feature/users'
PoWeiWu Nov 4, 2023
16628cf
feat: get users followers and followings route
PoWeiWu Nov 5, 2023
6a34c42
Merge branch 'feature/users'
PoWeiWu Nov 5, 2023
2306ef9
feat: fix model bug
Sunnylin0320 Nov 5, 2023
a308724
fix: modify auth middleware and fix return json format for user test
PoWeiWu Nov 5, 2023
8a4af4d
Merge branch 'feature/users'
PoWeiWu Nov 5, 2023
13ec545
fix users seed bug
Sunnylin0320 Nov 5, 2023
48000ac
feat: fix tweetsSeed bug
Sunnylin0320 Nov 6, 2023
d7d1629
feat: fix repliesSeed bug
Sunnylin0320 Nov 6, 2023
604b20a
Merge pull request #15 from paulwu-tw/feature/users
Sunnylin0320 Nov 6, 2023
064552e
Merge branch 'master' into feature/fixBug
Sunnylin0320 Nov 6, 2023
afe563c
feat: fix admin bug
Sunnylin0320 Nov 6, 2023
31897fb
Merge pull request #16 from paulwu-tw/feature/fixBug
paulwu-tw Nov 6, 2023
1b512ab
modify day.js and admin-controller
Sunnylin0320 Nov 7, 2023
3b4ee9a
fix user addLike
Sunnylin0320 Nov 7, 2023
848770e
fix addLike&removeLike bug
Sunnylin0320 Nov 7, 2023
63af749
fix like&reply bug
Sunnylin0320 Nov 7, 2023
bb9b5f6
modify getTweet repliesAmount
Sunnylin0320 Nov 7, 2023
14cc9fe
Merge pull request #17 from paulwu-tw/feature/fixBug
paulwu-tw Nov 8, 2023
ca94286
feat: get top 10 following user
PoWeiWu Nov 8, 2023
ac4340d
Merge branch 'master' into feature/users
PoWeiWu Nov 8, 2023
cba5021
Merge branch 'feature/users'
PoWeiWu Nov 8, 2023
98396e1
Merge pull request #18 from paulwu-tw/feature/users
Sunnylin0320 Nov 8, 2023
9c02572
Merge branch 'master' into feature/fixBug
Sunnylin0320 Nov 8, 2023
5330562
Merge branch 'master' into feature/fixBug
Sunnylin0320 Nov 8, 2023
8f9cb44
fix tweet and reply with no description
Sunnylin0320 Nov 8, 2023
497e656
feat: add get user likes and get replies
PoWeiWu Nov 8, 2023
23209ec
Merge pull request #19 from paulwu-tw/feature/fixBug
paulwu-tw Nov 8, 2023
3fc3b24
Merge branch 'master' into feature/users
PoWeiWu Nov 8, 2023
5f7629d
fix: get user likes bug
PoWeiWu Nov 8, 2023
3f14bc8
Merge pull request #20 from paulwu-tw/feature/users
Sunnylin0320 Nov 8, 2023
54e62d2
fix getReplies bug
Sunnylin0320 Nov 9, 2023
f8ae0bc
Merge pull request #21 from paulwu-tw/feature/fixBug
paulwu-tw Nov 9, 2023
c011ef0
feat: add relativeTimeFromNow for likes, tweets, replies
PoWeiWu Nov 9, 2023
f8d0d92
Merge branch 'master' into feature/users
PoWeiWu Nov 9, 2023
fc64b32
fix: get user replies route
PoWeiWu Nov 9, 2023
193ac77
fix: add default user avatat and cover when signup
PoWeiWu Nov 9, 2023
e84e3a7
fix: modify router, add introduction for followship response
PoWeiWu Nov 9, 2023
2b10232
fix: miss attribute
PoWeiWu Nov 9, 2023
539464c
Create README.md
Sunnylin0320 Nov 10, 2023
c55deb5
Merge pull request #22 from paulwu-tw/Sunnylin0320-patch-1
paulwu-tw Nov 10, 2023
a0590ca
feat: fix models and seed data
Sunnylin0320 Nov 10, 2023
31822f7
feat: add user seed data
Sunnylin0320 Nov 10, 2023
d79db67
Merge pull request #23 from paulwu-tw/feature/users
Sunnylin0320 Nov 10, 2023
a165ebb
Merge pull request #24 from paulwu-tw/feature/fixBug
paulwu-tw Nov 11, 2023
aa2e7e9
fix: missing JWT_SECRET for AC PR test
PoWeiWu Nov 12, 2023
bed2e29
fix: edit user validate if user exist
PoWeiWu Nov 12, 2023
022c6b0
Merge pull request #25 from paulwu-tw/feature/users
Sunnylin0320 Nov 12, 2023
8a989e8
fix: add admin get users cover attribute
PoWeiWu Nov 12, 2023
ccf2ddc
fix: edit user test error
PoWeiWu Nov 12, 2023
5ecfd82
fix: eslint
PoWeiWu Nov 12, 2023
25d5c4b
fix: error wording
PoWeiWu Nov 12, 2023
245eb28
Merge pull request #26 from paulwu-tw/feature/users
Sunnylin0320 Nov 12, 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
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
JWT_SECRET=
2 changes: 2 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/node_modules/*
/test/*
12 changes: 12 additions & 0 deletions .eslintrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
env:
browser: true
commonjs: true
es2021: true
extends:
- standard
parserOptions:
ecmaVersion: 12
rules:
arrow-parens:
- warn
- as-needed
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
temp/
.DS_Store
*.DS_Store

Expand Down
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
80 changes: 80 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# twitter-api-2020
ALPHA Camp | 學期 3 | Simple Twitter | 自動化測試檔 (前後分離組)
## 專案介紹
此專案為此為一個簡易的社群平臺的 API 專案,可進行推文、回覆推文等功能,後端使用 Node.js 並搭配 express.js框架做開發,並使用MySQL資料庫。


## 功能

### 前台(使用者)
- 註冊及登入功能
- 編輯自己的頁面
- 可瀏覽其他使用者的個人資料
- 追蹤和取消追蹤其他使用者
- 瀏覽全站所有推文
- 使用者可新增推文
- 瀏覽單筆推文及其回覆串
- 使用者可回覆他人的推文
- 喜歡及取消喜歡推文功能


### 後台(管理者)
- 登入功能
- 瀏覽全部使用者列表
- 瀏覽全站所有推文
- 可刪除任何人的推文


## 測試 / 種子帳號
| Role | Account | Password |
| :-------:| :-------: | :------: |
| 前台使用者 | user1 | 12345678 |
| 後台管理者 | root | 12345678 |


## 安裝及使用

### 環境建置
確認本地端已下載
- node.js
- MYSQL
- workbench

### 開始使用
1. 打開終端機(Terminal),Clone 此專案至本機電腦
```
$ git clone https://github.com/paulwu-tw/twitter-api-2020
```

2. 進入此專案資料夾
```
$ cd twitter-api-2020
```

3. 安裝本專案相依套件
```
$ npm install
```

4. 參考 `.env.example` 建立 `.env` 文件,並設置您的環境變數
```
JWT_SECRET=<setting by your own>
IMGUR_CLIENT_ID=<you imgur client id>
```

5. 於 `config/config.json` 文件中設定您資料庫的相關訊息

6. 建立資料表
```
$ npx sequelize db:migrate
```

7. 建立種子資料
```
$ npx sequelize db:seed:all
```

8. 輸入以下指令,啟動本專案
```
$ npm run dev
```
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
}
21 changes: 15 additions & 6 deletions app.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
if (process.env.NODE_ENV !== 'production') {
require('dotenv').config()
}

const express = require('express')
const helpers = require('./_helpers');
const passport = require('./config/passport')
const methodOverride = require('method-override')
const routes = require('./routes')
const cors = require('cors')

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

// use helpers.getUser(req) to replace req.user
function authenticated(req, res, next){
// passport.authenticate('jwt', { ses...
};
app.use(cors())
app.use(express.urlencoded({ extended: true }))
app.use(express.json())
app.use(passport.initialize())
app.use(methodOverride('_method'))

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

Expand Down
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": "JAWSDB_URL"
},
"travis": {
"username": "travis",
Expand Down
21 changes: 20 additions & 1 deletion config/passport.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,24 @@
const passport = require('passport')
const passportJWT = require('passport-jwt')
const { User } = require('../models')

const JWTStrategy = passportJWT.Strategy
const ExtractJWT = passportJWT.ExtractJwt

const jwtOptions = {
jwtFromRequest: ExtractJWT.fromAuthHeaderAsBearerToken(),
secretOrKey: process.env.JWT_SECRET || 'twitterapi'
}

module.exports = passport
passport.use(new JWTStrategy(jwtOptions, (jwtPayload, cb) => {
User.findByPk(jwtPayload.id, {
include: [
{ model: User, as: 'Followings' },
{ model: User, as: 'Followers' }
]
})
.then(user => cb(null, user))
.catch(err => cb(err))
}))

module.exports = passport
120 changes: 120 additions & 0 deletions controllers/admin-controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
const jwt = require('jsonwebtoken')
const { User, Tweet, Reply, Like } = require('../models')
const sequelize = require('sequelize')
const { relativeTimeFromNow } = require('../helpers/dayjs-helpers')

const adminController = {
signIn: (req, res, next) => {
try {
const userData = req.user.toJSON()
if (userData.role !== 'admin') {
throw new Error('帳號不存在')
}
delete userData.password
const token = jwt.sign(userData, process.env.JWT_SECRET, {
expiresIn: '30d'
})
res.json({
status: 'success',
data: {
token,
user: userData
}
})
} catch (err) {
next(err)
}
},
getUsers: async (req, res, next) => {
try {
const users = await User.findAll({
attributes: [
'id',
'name',
'account',
'avatar',
'cover',
[
sequelize.literal(
'(SELECT COUNT(*) FROM Tweets WHERE Tweets.UserId = User.id)'
),
'tweetsAmount'
],
[
sequelize.literal(
'(SELECT COUNT(*) FROM Likes WHERE Likes.TweetId IN (SELECT id FROM Tweets WHERE Tweets.UserId = User.id))'
),
'likesAmount'
],
[
sequelize.literal(
'(SELECT COUNT(*) FROM Followships WHERE Followships.followerId = User.id)'
),
'followingsAmount'
],
[
sequelize.literal(
'(SELECT COUNT(*) FROM Followships WHERE Followships.followingId = User.id)'
),
'followersAmount'
]
],
order: [
[sequelize.literal('tweetsAmount'), 'DESC'] // 按照推文數排序、由多至少
],
nest: true,
raw: true
})

return res.status(200).json(users)
} catch (err) {
return next(err)
}
},
getTweets: async (req, res, next) => {
try {
const tweets = await Tweet.findAll({
include: [
{
model: User,
attributes: ['id', 'account', 'name', 'avatar']
}
],
order: [['createdAt', 'DESC']],
raw: true,
nest: true
})
const data = tweets.map(tweet => ({
...tweet,
description: tweet.description.substring(0, 50),
createdAt: relativeTimeFromNow(tweet.createdAt)
}))

res.status(200).json(data)
} catch (err) {
next(err)
}
},
deleteTweet: async (req, res, next) => {
try {
const tweet = await Tweet.findByPk(req.params.id)
if (!tweet) throw new Error('此推文不存在!')

await Promise.all([
tweet.destroy(),
Reply.destroy({ where: { TweetId: tweet.id } }),
Like.destroy({ where: { TweetId: tweet.id } })
])

return res.status(200).json({
status: 'success',
message: '成功刪除推文!',
tweet
})
} catch (err) {
next(err)
}
}
}

module.exports = adminController
61 changes: 61 additions & 0 deletions controllers/followship-controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
const { User, Followship } = require('../models')
const helpers = require('../_helpers')

const followshipController = {
addFollowing: async (req, res, next) => {
try {
const followingId = req.body.id
const currentUserId = helpers.getUser(req).id

if (followingId === currentUserId) throw new Error("You can't follow yourself.")

const user = await User.findByPk(followingId)
if (!user || user.role === 'admin') throw new Error("User doesn't exist.")

const followship = await Followship.findOne({
where: {
followerId: currentUserId,
followingId
}
})

if (followship) throw new Error('You are already follow this user.')

const addFollowship = await Followship.create({
followerId: currentUserId,
followingId
})
res.status(200).json({ status: 'success', addFollowship })
} catch (err) {
next(err)
}
},
removeFollowing: async (req, res, next) => {
try {
const followingId = req.params.id
const currentUserId = helpers.getUser(req).id

const user = await User.findByPk(followingId)
if (!user || user.role === 'admin') throw new Error("User doesn't exist.")

const followship = await Followship.findOne({
where: {
followingId,
followerId: currentUserId
}
})

if (!followship) throw new Error("You're not follower")

await followship.destroy()
res.status(200).json({
status: 'success',
message: 'Following remove'
})
} catch (err) {
next(err)
}
}
}

module.exports = followshipController
Loading