var express = require('express'); var createError = require('http-errors') const bcrypt = require('bcryptjs'); const models = require('../../../models'); const utils = require('../../../libs/utils'); const auth = require('../../../libs/auth'); const router = express.Router(); router.get('/pager/headers', auth.need('read:own', 'user'), utils.pager.getHeadersBuilder(models.User)); router.get('/pager', auth.need('read:own', 'user'), (req, res, next) => { (async () => { if (!req.ac) throw createError(403, 'NO AC'); /**@type {AccessControl} */ let ac = req.ac; let readAny = ac.can('user').readAny('user').granted; if (readAny) next() else { req.query.base = { createBy: req.session.user._id }; next(); } })().catch(next); }, utils.pager.getListBuilder(models.User, [ { path: 'createBy', select: 'username' }, { path: 'roles', select: 'name' }, ], (item, req) => { return item.createBy && (item.createBy._id == req.session.user._id) } )); /** * user-create */ router.post('/', auth.need('create:own', 'user'), function (req, res, next) { (async function () { let { username, password, name, phone, email, roles } = req.body; if (!username || !password || !phone || !email || !name) throw createError(400, '缺少参数'); utils.validators.validatePhone(phone); utils.validators.validateUsername(username); utils.validators.validatePassword(password); let doc = await models.User.findOne({ $or: [{ username }, { phone }, { email }] }).select('username phone') .lean() .exec(); if (doc) throw createError(400, '用户名或手机号或邮箱已被占用'); let salt = await bcrypt.genSalt(10); password = await bcrypt.hash(password, salt); let createBy = req.session.user._id; let ipLastSignin = req.ip; let user = new models.User({ username, password, name, phone, email, roles, createBy, ipLastSignin }); await user.save(); res.json({ msg: 'ok', }) })().catch(next) }); router.get('/select/options', function (req, res, next) { (async function () { let docs = await models.User.find().select('username').lean(); docs = docs.map(u => ({ label: u.username, value: u._id })); res.json(docs); })().catch(next) }); router.get('/:id', auth.need('read:own', 'user'), function (req, res, next) { (async function () { utils.validators.validateId(req.params.id); let doc = await models.User.findById(req.params.id).select('-password').lean(); if (!doc) throw createError(404, 'Not found!'); if (!auth.can.readAny(req, 'user') && doc.createBy != req.session.user._id) throw createError(403, '权限不足'); res.json(doc); })().catch(next) }); router.patch('/:id', auth.need('update:own', 'user'), function (req, res, next) { (async function () { utils.validators.validateId(req.params.id); let doc = await models.User.findById(req.params.id); if (!doc) throw createError(404, 'Not found!'); let updates = {}; let editableFields = ['name', 'email', 'roles', 'epgs', 'phone', 'disabled']; Object.keys(req.body).filter(key => editableFields.includes(key)).forEach(key => { updates[key] = req.body[key]; }) doc.set(updates); console.log('user update:', doc.getChanges()); await doc.save(); if (doc.disabled === true) { await utils.session.destroyUser(req, doc._id); //清空用户session } //await utils.async.delay(1000); res.json({ msg: 'ok' }); })().catch(next) }); /** patch-password */ router.patch('/:id/password', auth.need('update:own', 'user'), function (req, res, next) { (async function () { utils.validators.validateId(req.params.id); let doc = await models.User.findById(req.params.id); if (!doc) throw createError(404, 'Not found!'); let password = randomPassword(); let salt = await bcrypt.genSalt(10); doc.password = await bcrypt.hash(password, salt); await utils.session.destroyUser(req, doc._id); await doc.save(); res.json({ name: doc.name, username: doc.username, password, }); })().catch(next) }); /** * 检查username占用 */ router.post('/check/username', auth.need('create:own', 'user'), function (req, res, next) { (async function () { let { id, username } = req.body; if (!username) throw createError(400, 'Invalid request'); let doc = await models.User.findOne({ username }).select('username').lean().exec(); if (doc && doc._id != id) throw createError(400, '已占用'); res.json({ msg: 'ok' }) })().catch(next) }); /** * 检查手机号占用 */ router.post('/check/phone', auth.need('create:own', 'user'), function (req, res, next) { (async function () { let { id, phone } = req.body; if (!phone) throw createError(400, 'Invalid request'); let doc = await models.User.findOne({ phone }).select('phone').lean().exec(); if (doc && doc._id != id) throw createError(400, '已占用'); res.json({ msg: 'ok' }) })().catch(next) }); /** * 检查邮箱占用 */ router.post('/check/email', auth.need('create:own', 'user'), function (req, res, next) { (async function () { let { id, email } = req.body; if (!email) throw createError(400, 'Invalid request'); let doc = await models.User.findOne({ email }).select('email').lean().exec(); if (doc && doc._id != id) throw createError(400, '已占用'); res.json({ msg: 'ok' }) })().catch(next) }); router.get('/session/list', auth.need('read:any', 'user'), function (req, res, next) { (async function () { let sessions = await utils.session.all(req); let data = sessions.map(s => { s.user.sesid = s.id; return s.user; }); res.json({ data }); })().catch(next) }); router.delete('/session/:id', auth.need('delete:any', 'user'), function (req, res, next) { (async function () { /**@type {any[]} */ let sessions = await utils.session.all(req); let ses = sessions.find(s => s.id == req.params.id); if (!ses) throw createError(404, 'session不存在'); //await utils.async.delay(1000); if (ses.id == req.session.id) throw createError(400, '不能删除你自己的session'); await utils.session.destroy(req, req.params.id); res.json({ msg: 'ok' }); })().catch(next) }); function randomPassword() { let wishlist = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz~!@-#$'; let pass = Array(20).fill(0).map(() => { return wishlist.charAt(Math.floor(Math.random() * wishlist.length)) }).join(''); console.log('pass', pass); return pass; } module.exports = router;