refactor: restructure entire project for human maintainability
Server: - Add Express framework, replace custom router/request parser - Create DAO layer (12 files) centralizing all 73 SQL queries - Rewrite 7 route files as thin Express controllers calling DAOs - Add SCF-to-Express adapter (lib/serverless.js) - Add auth middleware (middleware/auth.js) - Remove dead code from lib/auth.js Admin console: - Extract DataTable component (table + pagination) - Extract ConfirmModal component (modal + form styles) - Create listMixin for paginated list pages - Move form styles to common.css for slot compatibility - Refactor device + subscription pages as examples Miniprogram: - Split 734-line BLE monolith into 4 focused modules (protocol, connection, commands, barrel index) - Create API module (utils/api.js) with named functions - Create page utilities (utils/page.js) - Refactor index + profile pages to use API module
这个提交包含在:
+59
-62
@@ -1,78 +1,75 @@
|
||||
const jwt = require('jsonwebtoken')
|
||||
const { one, query } = require('../lib/db')
|
||||
const router = require('express').Router()
|
||||
const { ok, fail } = require('../lib/response')
|
||||
const { signUser, readBearer } = require('../lib/auth')
|
||||
const { code2Session } = require('../lib/wechat')
|
||||
const { writeLog } = require('../lib/log')
|
||||
const config = require('../config')
|
||||
const userDao = require('../dao/user.dao')
|
||||
const logDao = require('../dao/log.dao')
|
||||
|
||||
function register(router) {
|
||||
router.post('/api/v1/auth/login', async ctx => {
|
||||
const session = await code2Session(ctx.body.code || '')
|
||||
let user = await one('SELECT * FROM users WHERE openid = :openid', { openid: session.openid })
|
||||
if (!user) {
|
||||
const result = await query(
|
||||
'INSERT INTO users (openid, nickname, avatar, status) VALUES (:openid, :nickname, :avatar, 1)',
|
||||
{ openid: session.openid, nickname: '', avatar: '' }
|
||||
)
|
||||
user = await one('SELECT * FROM users WHERE user_id = :user_id', { user_id: result.insertId })
|
||||
await writeLog({ user_id: user.user_id, action: 'user_register', detail: '新用户注册', ip: ctx.ip })
|
||||
}
|
||||
const token = signUser(user)
|
||||
await writeLog({ user_id: user.user_id, action: 'user_login', detail: '用户登录', ip: ctx.ip })
|
||||
return ok({
|
||||
token,
|
||||
const wrap = fn => (req, res, next) => fn(req, res, next).catch(next)
|
||||
|
||||
router.post('/auth/login', wrap(async (req, res) => {
|
||||
const session = await code2Session(req.body.code || '')
|
||||
let user = await userDao.findByOpenid(session.openid)
|
||||
if (!user) {
|
||||
const result = await userDao.create(session.openid)
|
||||
user = await userDao.findById(result.insertId)
|
||||
await logDao.write({ user_id: user.user_id, action: 'user_register', detail: '新用户注册', ip: req.ip })
|
||||
}
|
||||
const token = signUser(user)
|
||||
await logDao.write({ user_id: user.user_id, action: 'user_login', detail: '用户登录', ip: req.ip })
|
||||
res.json(ok({
|
||||
token,
|
||||
user_id: String(user.user_id),
|
||||
user_info: {
|
||||
user_id: String(user.user_id),
|
||||
user_info: {
|
||||
user_id: String(user.user_id),
|
||||
nickname: user.nickname || '用户' + String(user.user_id),
|
||||
avatar: user.avatar || '',
|
||||
phone: user.phone || '',
|
||||
gender: user.gender || 0
|
||||
},
|
||||
expires_in: 604800
|
||||
})
|
||||
})
|
||||
nickname: user.nickname || '用户' + String(user.user_id),
|
||||
avatar: user.avatar || '',
|
||||
phone: user.phone || '',
|
||||
gender: user.gender || 0
|
||||
},
|
||||
expires_in: 604800
|
||||
}))
|
||||
}))
|
||||
|
||||
router.post('/api/v1/auth/refresh', async ctx => {
|
||||
const token = readBearer(ctx.headers)
|
||||
if (!token) return fail(1001, 'token_expired')
|
||||
router.post('/auth/refresh', wrap(async (req, res) => {
|
||||
const token = readBearer(req.headers)
|
||||
if (!token) return res.json(fail(1001, 'token_expired'))
|
||||
|
||||
let payload
|
||||
try {
|
||||
payload = jwt.verify(token, config.jwt.secret)
|
||||
} catch (err) {
|
||||
if (err.name === 'TokenExpiredError') {
|
||||
try {
|
||||
payload = jwt.verify(token, config.jwt.secret, { ignoreExpiration: true })
|
||||
} catch (_) {
|
||||
return fail(1001, 'token_expired')
|
||||
}
|
||||
const now = Math.floor(Date.now() / 1000)
|
||||
const gracePeriod = 3 * 24 * 60 * 60
|
||||
if (now - payload.exp > gracePeriod) {
|
||||
return fail(1001, 'token_expired')
|
||||
}
|
||||
} else {
|
||||
return fail(1001, 'token_expired')
|
||||
let payload
|
||||
try {
|
||||
payload = jwt.verify(token, config.jwt.secret)
|
||||
} catch (err) {
|
||||
if (err.name === 'TokenExpiredError') {
|
||||
try {
|
||||
payload = jwt.verify(token, config.jwt.secret, { ignoreExpiration: true })
|
||||
} catch (_) {
|
||||
return res.json(fail(1001, 'token_expired'))
|
||||
}
|
||||
const now = Math.floor(Date.now() / 1000)
|
||||
const gracePeriod = 3 * 24 * 60 * 60
|
||||
if (now - payload.exp > gracePeriod) {
|
||||
return res.json(fail(1001, 'token_expired'))
|
||||
}
|
||||
} else {
|
||||
return res.json(fail(1001, 'token_expired'))
|
||||
}
|
||||
}
|
||||
|
||||
if (payload.type !== 'user') return fail(1001, 'token_expired')
|
||||
if (payload.type !== 'user') return res.json(fail(1001, 'token_expired'))
|
||||
|
||||
// Check if token is within 7 days of expiry (for non-expired tokens)
|
||||
const now = Math.floor(Date.now() / 1000)
|
||||
const sevenDays = 7 * 24 * 60 * 60
|
||||
if (payload.exp && payload.exp > now && (payload.exp - now) > sevenDays) {
|
||||
return ok({ token, expires_in: payload.exp - now })
|
||||
}
|
||||
const now = Math.floor(Date.now() / 1000)
|
||||
const sevenDays = 7 * 24 * 60 * 60
|
||||
if (payload.exp && payload.exp > now && (payload.exp - now) > sevenDays) {
|
||||
return res.json(ok({ token, expires_in: payload.exp - now }))
|
||||
}
|
||||
|
||||
const user = await one('SELECT * FROM users WHERE user_id = :user_id AND status = 1', { user_id: payload.user_id })
|
||||
if (!user) return fail(1001, 'token_expired')
|
||||
const user = await userDao.findById(payload.user_id)
|
||||
if (!user) return res.json(fail(1001, 'token_expired'))
|
||||
|
||||
const newToken = signUser(user)
|
||||
return ok({ token: newToken, expires_in: 604800 })
|
||||
})
|
||||
}
|
||||
const newToken = signUser(user)
|
||||
res.json(ok({ token: newToken, expires_in: 604800 }))
|
||||
}))
|
||||
|
||||
module.exports = register
|
||||
module.exports = router
|
||||
|
||||
在新工单中引用
屏蔽一个用户