Compare commits
2 Commits
e61281ec76
...
4359654d72
| Author | SHA1 | Date |
|---|---|---|
|
|
4359654d72 | |
|
|
2f050489af |
|
|
@ -65,6 +65,17 @@ mongoose.connect(process.env.MONGODB_URI || 'mongodb://localhost:27017/e-scooter
|
|||
// ─── 路由(统一加 authMiddleware,按角色分级授权) ────────────
|
||||
//
|
||||
/// 管理后台 API(admin only)
|
||||
// 公开车辆列表(无需登录,供小程序/官网使用)
|
||||
const Vehicle = require('./models/Vehicle');
|
||||
app.get('/api/public/vehicles', async (req, res) => {
|
||||
try {
|
||||
const vehicles = await Vehicle.find({}).populate('currentOrderId');
|
||||
res.json({ success: true, data: vehicles });
|
||||
} catch (err) {
|
||||
res.status(500).json({ success: false, message: '服务器错误' });
|
||||
}
|
||||
});
|
||||
|
||||
app.use('/api/vehicles', rbacAuth('vehicles:read', 'vehicles:write'), require('./routes/vehicles'));
|
||||
app.use('/api/customers', rbacAuth('customers:read', 'customers:write'), require('./routes/customers'));
|
||||
app.use('/api/finance', rbacAuth('finance:read'), require('./routes/finance'));
|
||||
|
|
|
|||
|
|
@ -16,17 +16,19 @@ const loginLimiter = rateLimit({
|
|||
router.post('/login', loginLimiter, async (req, res) => {
|
||||
try {
|
||||
const { username, password } = req.body;
|
||||
const trimmedUsername = username ? username.trim() : '';
|
||||
const trimmedPassword = password ? password.trim() : '';
|
||||
|
||||
if (!username || !password) {
|
||||
if (!trimmedUsername || !trimmedPassword) {
|
||||
return res.status(400).json({ success: false, message: '用户名和密码不能为空' });
|
||||
}
|
||||
|
||||
const user = await User.findOne({ username }).select('+password');
|
||||
const user = await User.findOne({ username: trimmedUsername }).select('+password');
|
||||
if (!user || user.status !== 'active') {
|
||||
return res.status(401).json({ success: false, message: '用户名或密码错误' });
|
||||
}
|
||||
|
||||
const isMatch = await comparePassword(password, user.password);
|
||||
const isMatch = await comparePassword(trimmedPassword, user.password);
|
||||
if (!isMatch) {
|
||||
return res.status(401).json({ success: false, message: '用户名或密码错误' });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,15 +22,17 @@ const loginLimiter = rateLimit({
|
|||
router.post('/login', loginLimiter, validate(schemas.login), async (req, res) => {
|
||||
try {
|
||||
const { phone, password } = req.body;
|
||||
const trimmedPhone = phone ? phone.trim() : '';
|
||||
const trimmedPassword = password ? password.trim() : '';
|
||||
|
||||
// 用 select(false) 主动拉取 password 字段
|
||||
const rider = await Rider.findOne({ phone }).select('+password');
|
||||
const rider = await Rider.findOne({ phone: trimmedPhone }).select('+password');
|
||||
if (!rider) {
|
||||
return res.status(401).json({ success: false, message: '手机号或密码错误' });
|
||||
}
|
||||
|
||||
// bcrypt 比对密码
|
||||
const isMatch = await comparePassword(password, rider.password);
|
||||
const isMatch = await comparePassword(trimmedPassword, rider.password);
|
||||
if (!isMatch) {
|
||||
return res.status(401).json({ success: false, message: '手机号或密码错误' });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,12 +17,14 @@ const loginLimiter = rateLimit({
|
|||
router.post('/login', loginLimiter, async (req, res) => {
|
||||
try {
|
||||
const { username, password } = req.body;
|
||||
if (!username || !password) {
|
||||
const trimmedUsername = username ? username.trim() : '';
|
||||
const trimmedPassword = password ? password.trim() : '';
|
||||
if (!trimmedUsername || !trimmedPassword) {
|
||||
return res.status(400).json({ success: false, message: '用户名和密码不能为空' });
|
||||
}
|
||||
|
||||
// 从 User 表查 store 类型账号
|
||||
const user = await User.findOne({ username, type: 'store' }).select('+password');
|
||||
const user = await User.findOne({ username: trimmedUsername, type: 'store' }).select('+password');
|
||||
// 查关联的门店
|
||||
const Store = require('../models/Store');
|
||||
const store = await Store.findOne({ storeId: user.storeId });
|
||||
|
|
@ -30,7 +32,7 @@ router.post('/login', loginLimiter, async (req, res) => {
|
|||
return res.status(401).json({ success: false, message: '用户名或密码错误' });
|
||||
}
|
||||
|
||||
const isMatch = await comparePassword(password, user.password);
|
||||
const isMatch = await comparePassword(trimmedPassword, user.password);
|
||||
if (!isMatch) {
|
||||
return res.status(401).json({ success: false, message: '用户名或密码错误' });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ const { authMiddleware, requireRole } = require('../middleware/auth');
|
|||
const { validate } = require('../middleware/validate');
|
||||
const { schemas } = require('../middleware/validate');
|
||||
|
||||
// 获取所有车辆(公开,仅需登录)
|
||||
router.get('/', authMiddleware, async (req, res) => {
|
||||
// 获取所有车辆(公开,无需登录)
|
||||
router.get('/', async (req, res) => {
|
||||
try {
|
||||
const filter = {};
|
||||
// store 角色查询时校验 storeId 归属(只能看自己关联的门店)
|
||||
|
|
@ -25,8 +25,8 @@ router.get('/', authMiddleware, async (req, res) => {
|
|||
}
|
||||
});
|
||||
|
||||
// 获取单个车辆(公开)
|
||||
router.get('/:id', authMiddleware, async (req, res) => {
|
||||
// 获取单个车辆(公开,无需登录)
|
||||
router.get('/:id', async (req, res) => {
|
||||
try {
|
||||
const vehicle = await Vehicle.findById(req.params.id).populate('currentOrderId');
|
||||
if (!vehicle) return res.status(404).json({ success: false, message: '车辆不存在' });
|
||||
|
|
|
|||
Loading…
Reference in New Issue