yapi/server/controllers/project.js

617 lines
20 KiB
JavaScript
Raw Normal View History

2017-07-27 19:49:26 +08:00
import projectModel from '../models/project.js';
import yapi from '../yapi.js';
import baseController from './base.js';
import interfaceModel from '../models/interface.js';
import groupModel from '../models/group';
import commons from '../utils/commons.js';
import userModel from '../models/user.js';
2017-08-11 17:49:47 +08:00
import logModel from '../models/log.js';
2017-08-10 12:14:35 +08:00
import Mock from 'mockjs';
const send = require('koa-send');
2017-07-06 19:21:54 +08:00
class projectController extends baseController {
2017-07-27 19:49:26 +08:00
constructor(ctx) {
super(ctx);
2017-07-06 19:21:54 +08:00
this.Model = yapi.getInst(projectModel);
this.groupModel = yapi.getInst(groupModel);
2017-08-11 17:49:47 +08:00
this.logModel = yapi.getInst(logModel);
2017-07-06 19:21:54 +08:00
}
2017-07-27 19:49:26 +08:00
handleBasepath(basepath) {
if (!basepath) return "";
if (basepath === '/') return "";
2017-07-27 19:49:26 +08:00
if (basepath[0] !== '/') basepath = '/' + basepath;
if (basepath[basepath.length - 1] === '/') basepath = basepath.substr(0, basepath.length - 1);
if (!yapi.commons.verifyPath(basepath)) {
2017-07-20 16:14:20 +08:00
return false;
}
return basepath;
}
2017-07-27 19:49:26 +08:00
verifyDomain(domain) {
if (!domain) return false;
if (/^[a-zA-Z0-9\-_\.]+?\.[a-zA-Z0-9\-_\.]*?[a-zA-Z]{2,6}$/.test(domain)) {
2017-07-20 16:14:20 +08:00
return true;
}
return false;
}
2017-07-10 11:56:53 +08:00
/**
* 添加项目分组
* @interface /project/add
* @method POST
* @category project
* @foldnumber 10
* @param {String} name 项目名称不能为空
* @param {String} basepath 项目基本路径不能为空
* @param {Number} group_id 项目分组id不能为空
2017-08-11 17:24:50 +08:00
* @param {String} project_type private public
* @param {String} [desc] 项目描述
* @returns {Object}
2017-07-10 11:56:53 +08:00
* @example ./api/project/add.json
*/
async add(ctx) {
let params = ctx.request.body;
2017-07-26 14:22:59 +08:00
params = yapi.commons.handleParams(params, {
name: 'string',
basepath: 'string',
group_id: 'number',
2017-08-17 12:14:58 +08:00
desc: 'string',
color: 'string',
icon: 'string'
2017-07-27 19:49:26 +08:00
});
if (await this.checkAuth(params.group_id, 'group', 'edit') !== true) {
return ctx.body = yapi.commons.resReturn(null, 405, '没有权限');
}
2017-07-27 19:49:26 +08:00
if (!params.group_id) {
2017-07-06 19:21:54 +08:00
return ctx.body = yapi.commons.resReturn(null, 400, '项目分组id不能为空');
}
2017-07-27 19:49:26 +08:00
if (!params.name) {
2017-07-06 19:21:54 +08:00
return ctx.body = yapi.commons.resReturn(null, 400, '项目名不能为空');
}
2017-07-06 19:21:54 +08:00
let checkRepeat = await this.Model.checkNameRepeat(params.name);
2017-07-27 19:49:26 +08:00
if (checkRepeat > 0) {
return ctx.body = yapi.commons.resReturn(null, 401, '已存在的项目名');
2017-07-06 19:21:54 +08:00
}
params.basepath = params.basepath || '';
2017-07-27 19:49:26 +08:00
if ((params.basepath = this.handleBasepath(params.basepath)) === false) {
return ctx.body = yapi.commons.resReturn(null, 401, 'basepath格式有误');
2017-07-20 16:14:20 +08:00
}
let data = {
2017-07-06 19:21:54 +08:00
name: params.name,
desc: params.desc,
basepath: params.basepath,
2017-08-08 14:45:19 +08:00
members: [],
2017-08-09 16:16:35 +08:00
project_type: params.project_type || 'private',
2017-07-06 19:21:54 +08:00
uid: this.getUid(),
group_id: params.group_id,
2017-08-17 12:14:58 +08:00
icon: params.icon,
color: params.color,
add_time: yapi.commons.time(),
up_time: yapi.commons.time()
2017-07-27 19:49:26 +08:00
};
2017-07-06 19:21:54 +08:00
2017-07-27 19:49:26 +08:00
try {
let result = await this.Model.save(data);
2017-08-11 17:49:47 +08:00
let username = this.getUsername();
2017-08-16 17:12:01 +08:00
yapi.commons.saveLog({
2017-08-11 17:49:47 +08:00
content: `用户${username}添加了项目${params.name}`,
type: 'project',
uid: this.getUid(),
username: username,
2017-08-17 12:14:58 +08:00
typeid: params.group_id,
color: params.color,
icon: params.icon
2017-08-11 17:49:47 +08:00
});
ctx.body = yapi.commons.resReturn(result);
2017-07-27 19:49:26 +08:00
} catch (e) {
ctx.body = yapi.commons.resReturn(null, 402, e.message);
}
2017-07-06 19:21:54 +08:00
}
2017-07-27 19:49:26 +08:00
/**
2017-08-17 15:34:43 +08:00
* 添加项目成员
2017-07-27 19:49:26 +08:00
* @interface /project/add_member
* @method POST
* @category project
* @foldnumber 10
* @param {Number} id 项目id不能为空
* @param {String} member_uid 项目成员uid,不能为空
* @returns {Object}
* @example ./api/project/add_member.json
*/
async addMember(ctx) {
2017-07-06 19:21:54 +08:00
let params = ctx.request.body;
2017-07-27 19:49:26 +08:00
if (!params.member_uid) {
2017-07-06 19:21:54 +08:00
return ctx.body = yapi.commons.resReturn(null, 400, '项目成员uid不能为空');
}
2017-07-27 19:49:26 +08:00
if (!params.id) {
2017-07-06 19:21:54 +08:00
return ctx.body = yapi.commons.resReturn(null, 400, '项目id不能为空');
}
if (await this.checkAuth(params.id, 'project', 'edit') !== true) {
return ctx.body = yapi.commons.resReturn(null, 405, '没有权限');
}
2017-07-06 19:21:54 +08:00
var check = await this.Model.checkMemberRepeat(params.id, params.member_uid);
2017-07-27 19:49:26 +08:00
if (check > 0) {
return ctx.body = yapi.commons.resReturn(null, 400, '项目成员已存在');
2017-07-06 19:21:54 +08:00
}
2017-08-08 14:45:19 +08:00
params.role = params.role === 'owner' ? 'owner' : 'dev';
let userdata = await this.getUserdata(params.member_uid, params.role);
2017-08-08 14:45:19 +08:00
if(userdata === null){
return ctx.body = yapi.commons.resReturn(null, 400, '成员uid不存在')
}
2017-07-27 19:49:26 +08:00
try {
2017-08-08 14:45:19 +08:00
let result = await this.Model.addMember(params.id, userdata);
2017-08-11 17:49:47 +08:00
let username = this.getUsername();
2017-08-17 12:14:58 +08:00
let project = await this.Model.get(params.id);
2017-08-16 17:12:01 +08:00
yapi.commons.saveLog({
2017-08-11 17:49:47 +08:00
content: `用户${username}添加了项目成员${userdata.username}`,
type: 'project',
uid: this.getUid(),
username: username,
2017-08-17 12:14:58 +08:00
typeid: params.id,
color: project.color,
icon: project.icon
2017-08-11 17:49:47 +08:00
});
2017-07-06 19:21:54 +08:00
ctx.body = yapi.commons.resReturn(result);
2017-07-27 19:49:26 +08:00
} catch (e) {
ctx.body = yapi.commons.resReturn(null, 402, e.message);
2017-07-06 19:21:54 +08:00
}
}
2017-07-27 19:49:26 +08:00
/**
2017-08-17 15:34:43 +08:00
* 删除项目成员
2017-07-27 19:49:26 +08:00
* @interface /project/del_member
* @method POST
* @category project
* @foldnumber 10
* @param {Number} id 项目id不能为空
* @param {member_uid} uid 项目成员uid,不能为空
* @returns {Object}
* @example ./api/project/del_member.json
*/
2017-07-06 19:21:54 +08:00
2017-07-27 19:49:26 +08:00
async delMember(ctx) {
2017-07-06 19:21:54 +08:00
let params = ctx.request.body;
2017-07-27 19:49:26 +08:00
if (!params.member_uid) {
2017-07-06 19:21:54 +08:00
return ctx.body = yapi.commons.resReturn(null, 400, '项目成员uid不能为空');
}
2017-07-27 19:49:26 +08:00
if (!params.id) {
2017-07-06 19:21:54 +08:00
return ctx.body = yapi.commons.resReturn(null, 400, '项目id不能为空');
}
var check = await this.Model.checkMemberRepeat(params.id, params.member_uid);
2017-07-27 19:49:26 +08:00
if (check === 0) {
return ctx.body = yapi.commons.resReturn(null, 400, '项目成员不存在');
2017-07-06 19:21:54 +08:00
}
if (await this.checkAuth(params.id, 'project', 'danger') !== true) {
return ctx.body = yapi.commons.resReturn(null, 405, '没有权限');
}
2017-07-27 19:49:26 +08:00
try {
2017-07-06 19:21:54 +08:00
let result = await this.Model.delMember(params.id, params.member_uid);
2017-08-11 17:49:47 +08:00
let username = this.getUsername();
let project = await this.Model.get(params.id);
2017-08-16 17:12:01 +08:00
let member = await yapi.getInst(userModel).findById(params.member_uid);
yapi.commons.saveLog({
content: `用户${username}删除了项目${project.name}中的成员${member.username}`,
type: 'project',
uid: this.getUid(),
username: username,
2017-08-17 12:14:58 +08:00
typeid: params.id,
color: project.color,
icon: project.icon
2017-08-16 17:12:01 +08:00
});
2017-07-06 19:21:54 +08:00
ctx.body = yapi.commons.resReturn(result);
2017-07-27 19:49:26 +08:00
} catch (e) {
ctx.body = yapi.commons.resReturn(null, 402, e.message);
2017-07-06 19:21:54 +08:00
}
}
2017-08-08 14:45:19 +08:00
async getUserdata(uid, role){
role = role || 'dev';
let userInst = yapi.getInst(userModel);
let userData = await userInst.findById(uid);
if(!userData){
return null;
}
return {
role: role,
uid: userData._id,
username: userData.username,
email: userData.email
}
}
/**
* 获取项目成员列表
2017-07-18 15:13:47 +08:00
* @interface /project/get_member_list
* @method GET
* @category project
* @foldnumber 10
* @param {Number} id 项目id不能为空
* @return {Object}
* @example ./api/project/get_member_list.json
*/
async getMemberList(ctx) {
let params = ctx.request.query;
2017-07-27 19:49:26 +08:00
if (!params.id) {
return ctx.body = yapi.commons.resReturn(null, 400, '项目id不能为空');
}
try {
let project = await this.Model.get(params.id);
2017-08-08 14:45:19 +08:00
ctx.body = yapi.commons.resReturn(project.members);
2017-07-27 19:49:26 +08:00
} catch (e) {
ctx.body = yapi.commons.resReturn(null, 402, e.message);
}
}
2017-07-27 19:49:26 +08:00
/**
2017-08-17 15:34:43 +08:00
* 获取项目信息
2017-07-27 19:49:26 +08:00
* @interface /project/get
* @method GET
* @category project
* @foldnumber 10
* @param {Number} id 项目id不能为空
* @returns {Object}
* @example ./api/project/get.json
*/
2017-07-06 19:21:54 +08:00
2017-07-27 19:49:26 +08:00
async get(ctx) {
2017-07-06 19:21:54 +08:00
let params = ctx.request.query;
2017-07-27 19:49:26 +08:00
if (!params.id) {
2017-07-06 19:21:54 +08:00
return ctx.body = yapi.commons.resReturn(null, 400, '项目id不能为空');
}
2017-07-27 19:49:26 +08:00
try {
2017-07-06 19:21:54 +08:00
let result = await this.Model.get(params.id);
2017-08-15 18:36:48 +08:00
result = result.toObject();
delete result.members;
result.role = await this.getProjectRole(params.id, 'project');
2017-07-06 19:21:54 +08:00
ctx.body = yapi.commons.resReturn(result);
2017-07-27 19:49:26 +08:00
} catch (e) {
ctx.body = yapi.commons.resReturn(null, 402, e.message);
2017-07-06 19:21:54 +08:00
}
}
2017-07-10 11:56:53 +08:00
/**
* 获取项目列表
* @interface /project/list
* @method GET
* @category project
* @foldnumber 10
* @param {Number} group_id 项目group_id不能为空
* @returns {Object}
2017-07-10 11:56:53 +08:00
* @example ./api/project/list.json
*/
async list(ctx) {
2017-08-09 16:16:35 +08:00
let group_id = ctx.request.query.group_id
2017-07-18 15:13:47 +08:00
2017-07-27 19:49:26 +08:00
if (!group_id) {
2017-07-06 19:21:54 +08:00
return ctx.body = yapi.commons.resReturn(null, 400, '项目分组id不能为空');
}
2017-07-18 15:13:47 +08:00
2017-08-09 16:16:35 +08:00
let auth =await this.checkAuth(group_id, 'group', 'edit')
2017-07-27 19:49:26 +08:00
try {
let result = await this.Model.list(group_id, auth);
let uids = [];
2017-07-27 19:49:26 +08:00
result.forEach((item) => {
if (uids.indexOf(item.uid) === -1) {
uids.push(item.uid);
}
2017-07-27 19:49:26 +08:00
});
let _users = {}, users = await yapi.getInst(userModel).findByUids(uids);
2017-07-27 19:49:26 +08:00
users.forEach((item) => {
_users[item._id] = item;
2017-07-27 19:49:26 +08:00
});
2017-07-18 15:13:47 +08:00
ctx.body = yapi.commons.resReturn({
2017-08-15 17:55:52 +08:00
list: result
2017-07-27 19:49:26 +08:00
});
} catch (e) {
ctx.body = yapi.commons.resReturn(null, 402, e.message);
}
2017-07-06 19:21:54 +08:00
}
2017-07-10 11:56:53 +08:00
/**
* 删除项目
* @interface /project/del
* @method POST
* @category project
* @foldnumber 10
* @param {Number} id 项目id不能为空
* @returns {Object}
2017-07-10 11:56:53 +08:00
* @example ./api/project/del.json
*/
2017-07-27 19:49:26 +08:00
async del(ctx) {
try {
let id = ctx.request.body.id;
2017-07-27 19:49:26 +08:00
if (!id) {
2017-07-10 11:56:53 +08:00
return ctx.body = yapi.commons.resReturn(null, 400, '项目id不能为空');
}
2017-08-17 15:34:43 +08:00
if (await this.checkAuth(id, 'project', 'danger') !== true) {
2017-07-06 19:21:54 +08:00
return ctx.body = yapi.commons.resReturn(null, 405, '没有权限');
}
2017-08-16 10:56:42 +08:00
let interfaceInst = yapi.getInst(interfaceModel);
let interfaceColInst = yapi.getInst(interfaceColModel);
let interfaceCaseInst = yapi.getInst(interfaceCaseModel);
await interfaceInst.delByProjectId(id)
await interfaceCaseInst.delByProjectId(id)
await interfaceColInst.delByProjectId(id)
2017-07-06 19:21:54 +08:00
let result = await this.Model.del(id);
2017-07-10 20:02:44 +08:00
ctx.body = yapi.commons.resReturn(result);
2017-07-27 19:49:26 +08:00
} catch (err) {
ctx.body = yapi.commons.resReturn(null, 402, err.message);
}
2017-07-06 19:21:54 +08:00
}
async changeMemberRole(ctx){
let params = ctx.request.body;
let groupInst = yapi.getInst(groupModel);
if (!params.member_uid) {
return ctx.body = yapi.commons.resReturn(null, 400, '分组成员uid不能为空');
}
if (!params.id) {
return ctx.body = yapi.commons.resReturn(null, 400, '分组id不能为空');
}
var check = await groupInst.checkMemberRepeat(params.id, params.member_uid);
if (check === 0) {
return ctx.body = yapi.commons.resReturn(null, 400, '分组成员不存在');
}
if (await this.checkAuth(id, 'group', 'danger') !== true) {
return ctx.body = yapi.commons.resReturn(null, 405, '没有权限');
}
params.role = params.role === 'owner' ? 'owner' : 'dev';
try {
let result = await groupInst.changeMemberRole(params.id, params.member_uid, params.role);
2017-08-11 17:49:47 +08:00
let username = this.getUsername();
let project = await this.Model.get(params.id);
2017-08-16 17:12:01 +08:00
let member = await yapi.getInst(userModel).findByUids(params.member_uid);
yapi.commons.saveLog({
content: `用户${username}修改了项目${project.name}中成员${member.username}的角色为${params.role}`,
type: 'project',
uid: this.getUid(),
username: username,
2017-08-17 12:14:58 +08:00
typeid: params.id,
color: project.color,
icon: project.icon
2017-08-16 17:12:01 +08:00
});
ctx.body = yapi.commons.resReturn(result);
} catch (e) {
ctx.body = yapi.commons.resReturn(null, 402, e.message);
}
}
2017-07-10 11:56:53 +08:00
/**
* 编辑项目
* @interface /project/up
2017-07-18 15:48:05 +08:00
* @method POST
2017-07-10 11:56:53 +08:00
* @category project
* @foldnumber 10
* @param {Number} id 项目id不能为空
* @param {String} name 项目名称不能为空
* @param {String} basepath 项目基本路径不能为空
* @param {String} [desc] 项目描述
2017-07-10 20:02:44 +08:00
* @param {Array} [env] 项目环境配置
* @param {String} [env[].name] 环境名称
2017-07-21 11:46:44 +08:00
* @param {String} [env[].domain] 环境域名
* @returns {Object}
2017-07-10 11:56:53 +08:00
* @example ./api/project/up.json
*/
2017-07-27 19:49:26 +08:00
async up(ctx) {
try {
let id = ctx.request.body.id;
2017-07-06 20:53:26 +08:00
let params = ctx.request.body;
params.basepath = params.basepath || '';
2017-07-26 14:22:59 +08:00
params = yapi.commons.handleParams(params, {
name: 'string',
basepath: 'string',
group_id: 'number',
2017-08-17 12:14:58 +08:00
desc: 'string',
icon: 'string',
color: 'string'
2017-07-27 19:49:26 +08:00
});
if (!id) {
return ctx.body = yapi.commons.resReturn(null, 405, '项目id不能为空');
}
2017-07-06 20:53:26 +08:00
2017-08-08 14:45:19 +08:00
if (await this.checkAuth(id, 'project', 'edit') !== true) {
2017-07-06 19:21:54 +08:00
return ctx.body = yapi.commons.resReturn(null, 405, '没有权限');
}
let projectData = await this.Model.get(id);
2017-07-20 16:14:20 +08:00
2017-07-27 19:49:26 +08:00
if ((params.basepath = this.handleBasepath(params.basepath)) === false) {
return ctx.body = yapi.commons.resReturn(null, 401, 'basepath格式有误');
2017-07-20 16:14:20 +08:00
}
2017-07-27 19:49:26 +08:00
if (projectData.name === params.name) {
delete params.name;
}
2017-07-06 20:53:26 +08:00
2017-07-27 19:49:26 +08:00
if (params.name) {
2017-07-10 11:56:53 +08:00
let checkRepeat = await this.Model.checkNameRepeat(params.name);
2017-07-27 19:49:26 +08:00
if (checkRepeat > 0) {
return ctx.body = yapi.commons.resReturn(null, 401, '已存在的项目名');
2017-07-10 11:56:53 +08:00
}
2017-07-06 20:53:26 +08:00
}
2017-07-27 19:49:26 +08:00
let data = {
2017-07-10 11:56:53 +08:00
up_time: yapi.commons.time()
2017-07-27 19:49:26 +08:00
};
2017-07-06 20:53:26 +08:00
2017-07-27 19:49:26 +08:00
if (params.name) data.name = params.name;
if (params.desc) data.desc = params.desc;
2017-08-15 12:08:59 +08:00
if (params.basepath ) {
2017-07-10 11:56:53 +08:00
data.basepath = params.basepath;
2017-07-06 20:53:26 +08:00
}
2017-07-27 19:49:26 +08:00
if (params.env) data.env = params.env;
2017-08-17 12:14:58 +08:00
if(params.color) data.color = params.color;
if(params.icon) data.icon = params.icon;
2017-07-06 19:21:54 +08:00
let result = await this.Model.up(id, data);
2017-08-11 17:49:47 +08:00
let username = this.getUsername();
2017-08-16 17:12:01 +08:00
yapi.commons.saveLog({
content: `用户${username}更新了项目${projectData.name}`,
2017-08-11 17:49:47 +08:00
type: 'project',
uid: this.getUid(),
username: username,
2017-08-17 12:14:58 +08:00
typeid: id,
icon: params.icon,
color: params.color
2017-08-11 17:49:47 +08:00
});
2017-07-27 19:49:26 +08:00
ctx.body = yapi.commons.resReturn(result);
} catch (e) {
ctx.body = yapi.commons.resReturn(null, 402, e.message);
}
}
/**
* 模糊搜索项目名称或者组名称
* @interface /project/search
* @method GET
* @category project
* @foldnumber 10
* @param {String} q
* @return {Object}
2017-07-14 17:00:30 +08:00
* @example ./api/project/search.json
*/
async search(ctx) {
const { q } = ctx.request.query;
if (!q) {
2017-07-27 19:49:26 +08:00
return ctx.body = yapi.commons.resReturn(void 0, 400, 'No keyword.');
}
if (!yapi.commons.validateSearchKeyword(q)) {
2017-07-27 19:49:26 +08:00
return ctx.body = yapi.commons.resReturn(void 0, 400, 'Bad query.');
}
let projectList = await this.Model.search(q);
let groupList = await this.groupModel.search(q);
let projectRules = [
'_id',
'name',
'basepath',
'uid',
'env',
'members',
{ key: 'group_id', alias: 'groupId' },
{ key: 'up_time', alias: 'upTime' },
{ key: 'add_time', alias: 'addTime' }
];
let groupRules = [
'_id',
'uid',
2017-07-27 19:49:26 +08:00
{ key: 'group_name', alias: 'groupName' },
{ key: 'group_desc', alias: 'groupDesc' },
{ key: 'add_time', alias: 'addTime' },
{ key: 'up_time', alias: 'upTime' }
];
projectList = commons.filterRes(projectList, projectRules);
groupList = commons.filterRes(groupList, groupRules);
let queryList = {
project: projectList,
group: groupList
};
2017-07-27 19:49:26 +08:00
return ctx.body = yapi.commons.resReturn(queryList, 0, 'ok');
}
2017-08-10 12:14:35 +08:00
/**
* 下载项目的 Mock 数据
* @interface /project/download
* @method GET
* @category project
* @foldnumber 10
2017-08-15 12:08:59 +08:00
* @author wenbo.dong
2017-08-10 12:14:35 +08:00
* @param {String} project_id
*/
async download(ctx) {
2017-08-10 21:20:57 +08:00
const project_id = ctx.request.query.project_id;
let interfaceInst = yapi.getInst(interfaceModel);
// 根据 project_id 获取接口数据
let count = await interfaceInst.list(project_id);
if (!project_id) {
return ctx.body = yapi.commons.resReturn(null, 405, '项目id不能为空');
} else if (!count) {
return ctx.body = yapi.commons.resReturn(null, 401, '项目id不存在');
}
const arr = JSON.stringify(count.map(function(item) {
// 返回的json模板数据: item.res_body
const mockData = Mock.mock(
yapi.commons.json_parse(item.res_body)
);
return {
path: item.path,
mock: mockData
}
}));
const fileName = 'mock.js';
ctx.attachment(fileName);
await send(ctx, fileName, { root: __dirname + '/public' });
const res = `
var Mock = require('mockjs');
var xhook = require('xhook');
var data = ${arr};
function run() {
xhook.before(function(request, callback) {
setTimeout(function() {
var res;
data.forEach((item) => {
// 请求的接口在 data 中存在
if(request.url === item.path) {
res = {
status: 200,
text: Mock.mock(item.mock)
}
}
});
if (res) {
callback(res);
}else {
callback({ status: 405, text: '接口不存在' });
}
}, 500);
});
2017-08-10 12:14:35 +08:00
}
2017-08-10 21:20:57 +08:00
module.exports = run;`
.trim();
return ctx.body = res;
2017-08-10 12:14:35 +08:00
}
}
2017-07-06 19:21:54 +08:00
module.exports = projectController;