YApi : ./server/controllers/user.js
源代码
源代码
const userModel = require('../models/user.js'); const yapi = require('../yapi.js'); const baseController = require('./base.js'); const request = require('request'); const common = require('../utils/commons.js'); const interfaceModel = require('../models/interface.js'); const groupModel = require('../models/group.js'); const projectModel = require('../models/project.js'); const avatarModel = require('../models/avatar.js'); const jwt = require('jsonwebtoken'); class userController extends baseController { constructor(ctx) { super(ctx); this.Model = yapi.getInst(userModel); } /** * 用户登录接口 * @interface /user/login * @method POST * @category user * @foldnumber 10 * @param {String} email email名称,不能为空 * @param {String} password 密码,不能为空 * @returns {Object} * @example ./api/user/login.json */ async login(ctx) { //登录 let userInst = yapi.getInst(userModel); //创建user实体 let email = ctx.request.body.email; let password = ctx.request.body.password; if (!email) { return ctx.body = yapi.commons.resReturn(null, 400, 'email不能为空'); } if (!password) { return ctx.body = yapi.commons.resReturn(null, 400, '密码不能为空'); } let result = await userInst.findByEmail(email); if (!result) { return ctx.body = yapi.commons.resReturn(null, 404, '该用户不存在'); } else if (yapi.commons.generatePassword(password, result.passsalt) === result.password) { this.setLoginCookie(result._id, result.passsalt); return ctx.body = yapi.commons.resReturn({ username: result.username, role: result.role, uid: result._id, email: result.email, add_time: result.add_time, up_time: result.up_time, server_ip: yapi.WEBCONFIG.server_ip, type: 'site', study: result.study }, 0, 'logout success...'); } else { return ctx.body = yapi.commons.resReturn(null, 405, '密码错误'); } } /** * 退出登录接口 * @interface /user/logout * @method GET * @category user * @foldnumber 10 * @returns {Object} * @example ./api/user/logout.json */ async logout(ctx) { ctx.cookies.set('_yapi_token', null); ctx.cookies.set('_yapi_uid', null); ctx.body = yapi.commons.resReturn('ok'); } /** * 退出登录接口 * @interface /user/up_study * @method GET * @category user * @foldnumber 10 * @returns {Object} * @example */ async upStudy(ctx) { let userInst = yapi.getInst(userModel); //创建user实体 let data = { up_time: yapi.commons.time(), study: true }; try { let result = await userInst.update(this.getUid(), data); ctx.body = yapi.commons.resReturn(result); } catch (e) { ctx.body = yapi.commons.resReturn(null, 401, e.message); } } /** * 第三方登录需要提供一个request方法和 token字段,暂时只支持qunar第三方 * @return {email: String, username: String} */ thirdQunarLogin() { return { request: (token) => { return new Promise((resolve, reject) => { request('http://qsso.corp.qunar.com/api/verifytoken.php?token=' + token, function (error, response, body) { if (!error && response.statusCode == 200) { let result = JSON.parse(body); if (result && result.ret === true) { let ret = { email: result.userId + '@qunar.com', username: result.data.userInfo.name }; resolve(ret); } else { reject(result); } } reject(error); }); }); }, tokenField: 'token' }; } async loginByToken(ctx) { //let config = this.thirdQunarLogin(); try { let ret = await yapi.emitHook('third_login', ctx); let login = await this.handleThirdLogin(ret.email, ret.username); if (login === true) { yapi.commons.log('login success'); ctx.redirect('/group'); } } catch (e) { yapi.commons.log(e.message, 'error'); ctx.redirect('/'); } } async handleThirdLogin(email, username) { let user, data, passsalt; let userInst = yapi.getInst(userModel); try { user = await userInst.findByEmail(email); if (!user || !user._id) { passsalt = yapi.commons.randStr(); data = { username: username, password: yapi.commons.generatePassword(passsalt, passsalt), email: email, passsalt: passsalt, role: 'member', add_time: yapi.commons.time(), up_time: yapi.commons.time(), type: 'third' }; user = await userInst.save(data); await this.handlePrivateGroup(user._id, username, email); yapi.commons.sendMail({ to: email, contents: `亲爱的用户:
您好,感谢使用YApi平台,你的邮箱账号是:${email}
` }); } this.setLoginCookie(user._id, user.passsalt); return true; } catch (e) { console.error('third_login:', e.message); // eslint-disable-line return false; } } /** * 修改用户密码 * @interface /user/change_password * @method POST * @category user * @param {Number} uid 用户ID * @param {Number} [old_password] 旧密码, 非admin用户必须传 * @param {Number} password 新密码 * @return {Object} * @example ./api/user/change_password.json */ async changePassword(ctx) { let params = ctx.request.body; let userInst = yapi.getInst(userModel); if (!params.uid) { return ctx.body = yapi.commons.resReturn(null, 400, 'uid不能为空'); } if (!params.password) { return ctx.body = yapi.commons.resReturn(null, 400, '密码不能为空'); } if (this.getRole() !== 'admin' && params.uid != this.getUid()) { return ctx.body = yapi.commons.resReturn(null, 402, '没有权限'); } if (this.getRole() !== 'admin') { if (!params.old_password) { return ctx.body = yapi.commons.resReturn(null, 400, '旧密码不能为空'); } let user = await userInst.findById(params.uid); if (yapi.commons.generatePassword(params.old_password, user.passsalt) !== user.password) { return ctx.body = yapi.commons.resReturn(null, 402, '旧密码错误'); } } let passsalt = yapi.commons.randStr(); let data = { up_time: yapi.commons.time(), password: yapi.commons.generatePassword(params.password, passsalt), passsalt: passsalt }; try { let result = await userInst.update(params.uid, data); ctx.body = yapi.commons.resReturn(result); } catch (e) { ctx.body = yapi.commons.resReturn(null, 401, e.message); } } async handlePrivateGroup(uid, username, email){ var groupInst = yapi.getInst(groupModel); await groupInst.save({ uid: uid, group_name: 'User-' + uid, add_time: yapi.commons.time(), up_time: yapi.commons.time(), type: 'private' }) } setLoginCookie(uid, passsalt) { let token = jwt.sign({ uid: uid }, passsalt, { expiresIn: '7 days' }); this.ctx.cookies.set('_yapi_token', token, { expires: yapi.commons.expireDate(7), httpOnly: true }); this.ctx.cookies.set('_yapi_uid', uid, { expires: yapi.commons.expireDate(7), httpOnly: true }); } /** * 用户注册接口 * @interface /user/reg * @method POST * @category user * @foldnumber 10 * @param {String} email email名称,不能为空 * @param {String} password 密码,不能为空 * @param {String} [username] 用户名 * @returns {Object} * @example ./api/user/login.json */ async reg(ctx) { //注册 let userInst = yapi.getInst(userModel); let params = ctx.request.body; //获取请求的参数,检查是否存在用户名和密码 params = yapi.commons.handleParams(params, { username: 'string', password: 'string', email: 'string' }); if (!params.email) { return ctx.body = yapi.commons.resReturn(null, 400, '邮箱不能为空'); } if (!params.password) { return ctx.body = yapi.commons.resReturn(null, 400, '密码不能为空'); } let checkRepeat = await userInst.checkRepeat(params.email);//然后检查是否已经存在该用户 if (checkRepeat > 0) { return ctx.body = yapi.commons.resReturn(null, 401, '该email已经注册'); } let passsalt = yapi.commons.randStr(); let data = { username: params.username, password: yapi.commons.generatePassword(params.password, passsalt),//加密 email: params.email, passsalt: passsalt, role: 'member', add_time: yapi.commons.time(), up_time: yapi.commons.time(), type: "site" }; if (!data.username) { data.username = data.email.substr(0, data.email.indexOf('@')); } try { let user = await userInst.save(data); this.setLoginCookie(user._id, user.passsalt); await this.handlePrivateGroup(user._id, user.username, user.email); ctx.body = yapi.commons.resReturn({ uid: user._id, email: user.email, username: user.username, add_time: user.add_time, up_time: user.up_time, role: 'member', type: user.type, study: false }); yapi.commons.sendMail({ to: user.email, contents: `亲爱的用户:
您好,感谢使用YApi可视化接口平台,您的账号 ${params.email} 已经注册成功
` }); } catch (e) { ctx.body = yapi.commons.resReturn(null, 401, e.message); } } /** * 获取用户列表 * @interface /user/list * @method GET * @category user * @foldnumber 10 * @param {Number} [page] 分页页码 * @param {Number} [limit] 分页大小,默认为10条 * @returns {Object} * @example */ async list(ctx) { let page = ctx.request.query.page || 1, limit = ctx.request.query.limit || 10; const userInst = yapi.getInst(userModel); try { let user = await userInst.listWithPaging(page, limit); let count = await userInst.listCount(); return ctx.body = yapi.commons.resReturn({ count: count, total: Math.ceil(count / limit), list: user }); } catch (e) { return ctx.body = yapi.commons.resReturn(null, 402, e.message); } } /** * 获取用户个人信息 * @interface /user/find * @method GET * @param id 用户uid * @category user * @foldnumber 10 * @returns {Object} * @example */ async findById(ctx) { //根据id获取用户信息 try { let userInst = yapi.getInst(userModel); let id = ctx.request.query.id; if (!id) { return ctx.body = yapi.commons.resReturn(null, 400, 'uid不能为空'); } let result = await userInst.findById(id); if (!result) { return ctx.body = yapi.commons.resReturn(null, 402, '不存在的用户'); } return ctx.body = yapi.commons.resReturn({ uid: result._id, username: result.username, email: result.email, role: result.role, type: result.type, add_time: result.add_time, up_time: result.up_time }); } catch (e) { return ctx.body = yapi.commons.resReturn(null, 402, e.message); } } /** * 删除用户,只有admin用户才有此权限 * @interface /user/del * @method POST * @param id 用户uid * @category user * @foldnumber 10 * @returns {Object} * @example */ async del(ctx) { //根据id删除一个用户 try { if (this.getRole() !== 'admin') { return ctx.body = yapi.commons.resReturn(null, 402, 'Without permission.'); } let userInst = yapi.getInst(userModel); let id = ctx.request.body.id; if (!id) { return ctx.body = yapi.commons.resReturn(null, 400, 'uid不能为空'); } let result = await userInst.del(id); ctx.body = yapi.commons.resReturn(result); } catch (e) { ctx.body = yapi.commons.resReturn(null, 402, e.message); } } /** * 更新用户个人信息 * @interface /user/update * @method POST * @param uid 用户uid * @param [role] 用户角色,只有管理员有权限修改 * @param [username] String * @param [email] String * @category user * @foldnumber 10 * @returns {Object} * @example */ async update(ctx) { //更新用户信息 try { let params = ctx.request.body; params = yapi.commons.handleParams(params, { username: 'string', email: 'string' }); if (this.getRole() !== 'admin' && params.uid != this.getUid()) { return ctx.body = yapi.commons.resReturn(null, 401, '没有权限'); } let userInst = yapi.getInst(userModel); let id = params.uid; if (!id) { return ctx.body = yapi.commons.resReturn(null, 400, 'uid不能为空'); } let userData = await userInst.findById(id); if (!userData) { return ctx.body = yapi.commons.resReturn(null, 400, 'uid不存在'); } let data = { up_time: yapi.commons.time() }; params.username && (data.username = params.username); params.email && (data.email = params.email); if (data.email) { var checkRepeat = await userInst.checkRepeat(data.email);//然后检查是否已经存在该用户 if (checkRepeat > 0) { return ctx.body = yapi.commons.resReturn(null, 401, '该email已经注册'); } } let member = { uid: id, username: data.username || userData.username, email: data.email || userData.email } let groupInst = yapi.getInst(groupModel); await groupInst.updateMember(member) let projectInst = yapi.getInst(projectModel); await projectInst.updateMember(member) let result = await userInst.update(id, data); ctx.body = yapi.commons.resReturn(result); } catch (e) { ctx.body = yapi.commons.resReturn(null, 402, e.message); } } /** * 上传用户头像 * @interface /user/upload_avatar * @method POST * @param {*} basecode base64编码,通过h5 api传给后端 * @category user * @returns {Object} * @example */ async uploadAvatar(ctx) { try { let basecode = ctx.request.body.basecode; if(!basecode){ return ctx.body = yapi.commons.resReturn(null, 400, 'basecode不能为空') } let pngPrefix = 'data:image/png;base64,'; let jpegPrefix = 'data:image/jpeg;base64,'; let type; if(basecode.substr(0, pngPrefix.length ) === pngPrefix){ basecode = basecode.substr(pngPrefix.length); type = 'image/png'; }else if(basecode.substr(0, jpegPrefix.length ) === jpegPrefix){ basecode = basecode.substr(jpegPrefix.length); type = 'image/jpeg'; }else{ return ctx.body = yapi.commons.resReturn(null, 400, '仅支持jpeg和png格式的图片') } let strLength = basecode.length; if(parseInt(strLength-(strLength/8)*2) > 200000){ return ctx.body = yapi.commons.resReturn(null, 400, '图片大小不能超过200kb'); } let avatarInst = yapi.getInst(avatarModel); let result = await avatarInst.up(this.getUid(), basecode, type) ctx.body = yapi.commons.resReturn(result); } catch (e) { ctx.body = yapi.commons.resReturn(null, 401, e.message); } } /** * 根据用户uid头像 * @interface /user/avatar * @method GET * @param {*} uid * @category user * @returns {Object} * @example */ async avatar(ctx) { try{ let uid = ctx.query.uid ? ctx.query.uid: this.getUid(); let avatarInst = yapi.getInst(avatarModel); let data = await avatarInst.get(uid); let dataBuffer, type; if(!data || !data.basecode){ dataBuffer = yapi.fs.readFileSync(yapi.path.join(yapi.WEBROOT, 'static/image/avatar.png')); type = 'image/png' }else{ type = data.type; dataBuffer = new Buffer(data.basecode, 'base64'); } ctx.set('Content-type', type); ctx.body = dataBuffer; }catch(err){ ctx.body = 'error:' + err.message } } /** * 模糊搜索用户名或者email * @interface /user/search * @method GET * @category user * @foldnumber 10 * @param {String} q * @return {Object} * @example ./api/user/search.json */ async search(ctx) { const { q } = ctx.request.query; if (!q) { return ctx.body = yapi.commons.resReturn(void 0, 400, 'No keyword.'); } if (!yapi.commons.validateSearchKeyword(q)) { return ctx.body = yapi.commons.resReturn(void 0, 400, 'Bad query.'); } let queryList = await this.Model.search(q); let rules = [ { key: '_id', alias: 'uid' }, 'username', 'email', 'role', { key: 'add_time', alias: 'addTime' }, { key: 'up_time', alias: 'upTime' } ]; let filteredRes = common.filterRes(queryList, rules); return ctx.body = yapi.commons.resReturn(filteredRes, 0, 'ok'); } /** * 根据路由id初始化项目数据 * @interface /user/project * @method GET * @category user * @foldnumber 10 * @param {String} type 可选group|interface|project * @param {Number} id * @return {Object} * @example */ async project(ctx) { let { id, type } = ctx.request.query; let result = {}; try { if (type === 'interface') { let interfaceInst = yapi.getInst(interfaceModel); let interfaceData = await interfaceInst.get(id) result.interface = interfaceData; type = 'project'; id = interfaceData.project_id; } if (type === 'project') { let projectInst = yapi.getInst(projectModel); let projectData = await projectInst.get(id); result.project = projectData.toObject(); let ownerAuth = await this.checkAuth(id, 'project', 'danger'), devAuth; if(ownerAuth){ result.project.role = 'owner' }else{ devAuth = await this.checkAuth(id, 'project', 'site'); if(devAuth){ result.project.role = 'dev' }else{ result.project.role = 'member' } } type = 'group'; id = projectData.group_id; } if (type === 'group') { let groupInst = yapi.getInst(groupModel); let groupData = await groupInst.get(id); result.group = groupData.toObject(); let ownerAuth = await this.checkAuth(id, 'group', 'danger'), devAuth; if(ownerAuth){ result.group.role = 'owner' }else{ devAuth = await this.checkAuth(id, 'group', 'site'); if(devAuth){ result.group.role = 'dev' }else{ result.group.role = 'member' } } } return ctx.body = yapi.commons.resReturn(result) } catch (e) { return ctx.body = yapi.commons.resReturn(result, 422, e.message) } } } module.exports = userController;