2
0
mirror of https://github.com/YMFE/yapi.git synced 2025-04-12 15:10:23 +08:00

Merge branch 'master' into patch-1

This commit is contained in:
aweleey 2021-08-23 15:46:29 +08:00 committed by GitHub
commit d6f2595326
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 177 additions and 88 deletions

@ -1,3 +1,24 @@
## v1.9.2
* fix: 修复高级 mock 无效的bug
* opti: 对登录 email 空格的过滤
* fix: 修复deepMath 增加对原型属性比较
## v1.9.1
* 修复因 mongodb 一个废弃报错导致部署不成功问题
## v1.9.0
* 修复测试集合部分情况下闪动问题
* 修改ldap filter的匹配规则使其可以匹配&和|操作符 Merge pull request #1631 from vvkkhjt/master
* support switch_notice for /interface/save Merge pull request #1646 from tangcent/feature/openapi_notice
* 自动化测试时服务端测试node默认2分钟没有返回就直接断掉连接可以手动设置一个超时时间 Merge pull request #1675 from liugddx/master
* 修复导出的swagger.json 中 required 一直是 false 的 bug
* 修复 schema2json传required参数时导致faker失败
* 修改ldap filter的匹配规则
* 更新 sm2tsservice 3.2.0及以后版本的使用配置
## v1.8.8
* 更新了 cross-request [教程](https://juejin.im/post/5e3bbd986fb9a07ce152b53d),发布了最新的 3.1 版本
## v1.8.7
* 因 chrome 官方下架了 yapi 扩展,整理了本地安装教程

@ -1,7 +1,8 @@
## YApi 可视化接口管理平台
示例站点:
<p><a target="_blank" href="http://yapi.demo.qunar.com">yapi.demo.qunar.com</a></p>
体验地址:
[http://yapi.smart-xwork.cn/](http://yapi.smart-xwork.cn/)
文档:
<p><a target="_blank" href="https://hellosean1025.github.io/yapi">hellosean1025.github.io/yapi</a></p>
@ -59,6 +60,7 @@ YApi 是<strong>高效</strong>、<strong>易用</strong>、<strong>功能强大
* [使用 YApi 管理 API 文档,测试, mock](https://juejin.im/post/5acc879f6fb9a028c42e8822)
* [自动更新 Swagger 接口数据到 YApi 平台](https://juejin.im/post/5af500e251882567096140dd)
* [自动化测试](https://juejin.im/post/5a388892f265da430e4f4681)
* [GTest(基于YApi)接口研发效能提升10倍 实战](https://mp.weixin.qq.com/s/z66f7bRX8aAOppAtBIB7Uw)
### YApi 插件
* [yapi sso 登录插件](https://github.com/YMFE/yapi-plugin-qsso)
@ -74,19 +76,22 @@ YApi 是<strong>高效</strong>、<strong>易用</strong>、<strong>功能强大
### 代码生成
* [yapi-to-typescript根据 YApi 的接口定义生成 TypeScript 的请求函数](https://github.com/fjc0k/yapi-to-typescript)
* [yapi-gen-js-code: 根据 YApi 的接口定义生成 javascript 的请求函数](https://github.com/hellosean1025/yapi-gen-js-code)
* [SwiftJSONModeler:根据 YApi 的接口生成 Swift 模型代码](https://github.com/CodeOcenS/SwiftJSONModeler)
### YApi docker部署非官方
* [使用 alpine 版 docker 镜像快速部署 yapi](https://www.jianshu.com/p/a97d2efb23c5)
* [docker-yapi](https://github.com/Ryan-Miao/docker-yapi)
* [docker-yapi: 基于官方yapi-cli的docker-compose方案](https://github.com/Ryan-Miao/docker-yapi)
* [docker-compose一键部署yapi](https://github.com/jinfeijie/yapi)
* [docker-YApi: 更易用的 YApi 镜像](https://github.com/fjc0k/docker-YApi)
* [使用DockerCompose构建部署Yapi](https://github.com/MyHerux/daily-code/blob/master/Program/%E5%B7%A5%E5%85%B7%E7%AF%87/Yapi/%E4%BD%BF%E7%94%A8DockerCompose%E6%9E%84%E5%BB%BA%E9%83%A8%E7%BD%B2Yapi.md)
### YApi 一些工具
* [Api Generator](https://github.com/Forgus/api-generator) 接口文档自动生成插件(零入侵)
* [mysql服务http工具,可配合做自动化测试](https://github.com/hellosean1025/http-mysql-server)
* [idea 一键上传接口到yapi插件](https://github.com/diwand/YapiIdeaUploadPlugin)
* [idea 接口上传调试插件 easy-yapi](https://easyyapi.com/)
* [执行 postgres sql 的服务](https://github.com/shouldnotappearcalm/http-postgres-server)
* [Yapi X 一键生成接口文档, 上传到yapi, rap2, eolinker等IDEA插件](https://github.com/jetplugins/yapix)
### YApi 的一些客户
* 去哪儿
@ -107,6 +112,7 @@ YApi 是<strong>高效</strong>、<strong>易用</strong>、<strong>功能强大
* VIPKID
* 马蜂窝
* 伴鱼
* 旷视科技
### Authors
* [hellosean1025](https://github.com/hellosean1025)

5
SECURITY.md Normal file

@ -0,0 +1,5 @@
# Security Policy
## Reporting a Vulnerability
Please report security issues at js@liyi.im

@ -44,14 +44,9 @@ function CheckCrossInstall(props) {
</a>
</div> */}
<div>
<a target="blank" href="/api/interface/download_crx">
{' '}
[手动下载]{' '}
</a>
<span> zip 文件解压后将 crx 文件拖入到 chrome://extensions/(注意:一定要开启开发者模式) </span>
<a target="blank" href="https://juejin.im/post/5e3bbd986fb9a07ce152b53d">
{' '}
[详细安装教程]{' '}
[谷歌请求插件详细安装教程]{' '}
</a>
</div>
</div>

@ -2,7 +2,7 @@ import React, { Component } from 'react';
import { Table } from 'antd';
import json5 from 'json5';
import PropTypes from 'prop-types';
import { schemaTransformToTable } from '../../../common/shema-transformTo-table.js';
import { schemaTransformToTable } from '../../../common/schema-transformTo-table.js';
import _ from 'underscore';
import './index.scss';

@ -85,7 +85,7 @@ export default class InterfaceCaseContent extends Component {
const { actionId } = params;
currCaseId = +actionId || +currCaseId || result.payload.data.data[0].caseList[0]._id;
let currColId = this.getColId(result.payload.data.data, currCaseId);
this.props.history.push('/project/' + params.id + '/interface/case/' + currCaseId);
// this.props.history.push('/project/' + params.id + '/interface/case/' + currCaseId);
await this.props.fetchCaseData(currCaseId);
this.props.setColData({ currCaseId: +currCaseId, currColId, isShowCol: false });
// 获取当前case 下的环境变量

@ -175,7 +175,7 @@ class InterfaceColContent extends Component {
const params = this.props.match.params;
const { actionId } = params;
this.currColId = currColId = +actionId || result.payload.data.data[0]._id;
this.props.history.push('/project/' + params.id + '/interface/col/' + currColId);
// this.props.history.push('/project/' + params.id + '/interface/col/' + currColId);
if (currColId && currColId != 0) {
await this.handleColIdChange(currColId)
}

@ -14,6 +14,7 @@ import axios from 'axios';
import ImportInterface from './ImportInterface';
import { Input, Icon, Button, Modal, message, Tooltip, Tree, Form } from 'antd';
import { arrayChangeIndex } from '../../../../common.js';
import _ from 'underscore'
const TreeNode = Tree.TreeNode;
const FormItem = Form.Item;
@ -148,7 +149,7 @@ export default class InterfaceColMenu extends Component {
this.setState({ expands: keys });
};
onSelect = keys => {
onSelect = _.debounce(keys => {
if (keys.length) {
const type = keys[0].split('_')[0];
const id = keys[0].split('_')[1];
@ -168,7 +169,7 @@ export default class InterfaceColMenu extends Component {
this.setState({
expands: null
});
};
}, 500);
showDelColConfirm = colId => {
let that = this;

@ -548,9 +548,12 @@ class InterfaceEditForm extends Component {
this.state.bulkValue.split('\n').forEach((item, index) => {
let valueItem = Object.assign({}, curValue[index] || dataTpl[this.state.bulkName]);
valueItem.name = item.split(':')[0];
valueItem.example = item.split(':')[1] || '';
newValue.push(valueItem);
let indexOfColon = item.indexOf(':');
if (indexOfColon!==-1) {
valueItem.name = item.substring(0, indexOfColon);
valueItem.example = item.substring(indexOfColon + 1) || '';
newValue.push(valueItem);
}
});
this.props.form.setFieldsValue({[this.state.bulkName]: newValue});

@ -85,7 +85,9 @@ exports.isDeepMatch = function(obj, properties) {
}
let match = true;
for (var i in properties) {
let keys = Object.keys(properties)
for (let index=0; index< keys.length; index++) {
let i = keys[index];
if (!Compare(obj[i], properties[i])) {
match = false;
break;

@ -1,4 +1,4 @@
const schema = require('./shema-transformTo-table.js');
const schema = require('./schema-transformTo-table.js');
const _ = require('underscore');
const json_parse = function(json) {

@ -1,6 +1,7 @@
{
"port": "3000",
"adminAccount": "admin@admin.com",
"timeout":120000,
"db": {
"servername": "127.0.0.1",
"DATABASE": "yapi",

@ -26,7 +26,7 @@ npm run dev #启动开发服务器
可参考 项目vendors/exts 目录下的插件
在 vendors/node_modules 下新建 yapi-plugin-demo 目录和 npm init,最后生成的目录接口如下
在 vendors/node_modules 下新建 yapi-plugin-demo 目录和 npm init,最后生成的目录结构如下
```
yapi-plugin-demo
client.js //客户端入口文件

@ -7,4 +7,5 @@ Fork [yapi](https://github.com/YMFE/yapi), 然后修改 docs/documents/plugin-li
* [qsso](https://github.com/ymfe/yapi-plugin-qsso) sso 第三方登录
* [import-rap](https://github.com/wxxcarl/yapi-plugin-import-rap) 从rap中导入项目
* [export-docx-data](https://github.com/inceptiongt/Yapi-plugin-export-docx-data) 数据导出docx文档
* [import-swagger-customize](https://github.com/follow-my-heart/yapi-plugin-import-swagger-customize) 导入指定swagger接口
* [import-swagger-customize](https://github.com/follow-my-heart/yapi-plugin-import-swagger-customize) 导入指定swagger接口
* [autotest](https://github.com/duicym/yapi-plugin-autotest) 定时自动测试发送钉钉插件

@ -207,6 +207,6 @@ module.exports = function() {
// mock 脚本
let script = data.mock_script;
yapi.commons.handleMockScript(script, context);
await yapi.commons.handleMockScript(script, context);
});
};

@ -167,7 +167,7 @@ class exportSwaggerController extends baseController {
name: p.name,
in: 'header',
description: `${p.name} (Only:${p.value})`,
required: p.required === 1,
required: Number(p.required) === 1,
type: 'string', //always be type string
default: p.value
});
@ -187,7 +187,7 @@ class exportSwaggerController extends baseController {
paramArray.push({
name: p.name,
in: 'query',
required: p.required === 1,
required: Number(p.required) === 1,
description: p.desc,
type: 'string' //always be type string
});
@ -200,7 +200,7 @@ class exportSwaggerController extends baseController {
paramArray.push({
name: p.name,
in: 'formData',
required: p.required === 1,
required: Number(p.required) === 1,
description: p.desc,
type: p.type === 'text' ? 'string' : 'file' //in this time .formData type have only text or file
});
@ -285,4 +285,4 @@ class exportSwaggerController extends baseController {
}
}
module.exports = exportSwaggerController;
module.exports = exportSwaggerController;

@ -26,6 +26,22 @@ const compareVersions = require('compare-versions');
) {
Object.assign(res, res.content['application/json']);
delete res.content;
}
if (
res.content &&
res.content['application/hal+json'] &&
typeof res.content['application/hal+json'] === 'object'
) {
Object.assign(res, res.content['application/hal+json']);
delete res.content;
}
if (
res.content &&
res.content['*/*'] &&
typeof res.content['*/*'] === 'object'
) {
Object.assign(res, res.content['*/*']);
delete res.content;
}
});
if (api.requestBody) {
@ -240,6 +256,9 @@ const compareVersions = require('compare-versions');
break;
case 'formData':
defaultParam.type = param.type === 'file' ? 'file' : 'text';
if (param.example) {
defaultParam.example = param.example;
}
api.req_body_form.push(defaultParam);
break;
case 'header':

@ -96,9 +96,9 @@ class syncUtils {
//更新之前判断本次swagger json数据是否跟上次的相同,相同则不更新
if (newSwaggerJsonData && oldSyncJob.old_swagger_content && oldSyncJob.old_swagger_content == md5(newSwaggerJsonData)) {
//记录日志
this.saveSyncLog(0, syncMode, "接口无更新", uid, projectId);
// this.saveSyncLog(0, syncMode, "接口无更新", uid, projectId);
oldSyncJob.last_sync_time = yapi.commons.time();
await this.syncModel.upById(projectId, oldSyncJob);
await this.syncModel.upById(oldSyncJob._id, oldSyncJob);
return;
}

7
package-lock.json generated

@ -1,6 +1,6 @@
{
"name": "yapi-vendor",
"version": "1.8.6",
"version": "1.9.1",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@ -22742,6 +22742,11 @@
"indexof": "0.0.1"
}
},
"vm2": {
"version": "3.9.1",
"resolved": "https://registry.npm.taobao.org/vm2/download/vm2-3.9.1.tgz",
"integrity": "sha1-Ebk5Cgd0X8+wtoIHjoT8rRR6rpc="
},
"vows": {
"version": "0.6.0",
"resolved": "http://registry.npm.taobao.org/vows/download/vows-0.6.0.tgz",

@ -1,6 +1,6 @@
{
"name": "yapi-vendor",
"version": "1.8.7",
"version": "1.9.2",
"description": "YAPI",
"main": "server/app.js",
"scripts": {
@ -74,15 +74,17 @@
"node-schedule": "^1.3.2",
"nodemailer": "4.0.1",
"os": "0.1.1",
"qs": "^6.7.0",
"request": "2.81.0",
"safeify": "^5.0.5",
"sha.js": "2.4.9",
"sha1": "1.1.1",
"swagger-client": "^3.5.1",
"tslib": "1.8.0",
"underscore": "1.8.3",
"url": "0.11.0",
"yapi-plugin-qsso": "^1.1.0",
"qs": "^6.7.0"
"vm2": "^3.8.4",
"yapi-plugin-qsso": "^1.1.0"
},
"devDependencies": {
"antd": "3.2.2",

@ -54,9 +54,14 @@ app.use(async (ctx, next) => {
await next();
});
app.use(koaStatic(yapi.path.join(yapi.WEBROOT, 'static'), { index: indexFile, gzip: true }));
app.listen(yapi.WEBCONFIG.port);
const server = app.listen(yapi.WEBCONFIG.port);
server.setTimeout(yapi.WEBCONFIG.timeout);
commons.log(
`服务已启动,请打开下面链接访问: \nhttp://127.0.0.1${
yapi.WEBCONFIG.port == '80' ? '' : ':' + yapi.WEBCONFIG.port

@ -51,7 +51,8 @@ class baseController {
'/api/interface/list_cat',
'/api/project/get',
'/api/plugin/export',
'/api/project/up'
'/api/project/up',
'/api/plugin/exportSwagger'
];
let params = Object.assign({}, ctx.query, ctx.request.body);

@ -161,6 +161,7 @@ class interfaceController extends baseController {
path: minLengthStringField,
method: minLengthStringField,
message: minLengthStringField,
switch_notice: 'boolean',
dataSync: 'string'
},
addAndUpCommonField
@ -326,7 +327,6 @@ class interfaceController extends baseController {
* @param {String} [desc] 接口描述
* @returns {Object}
*/
async save(ctx) {
let params = ctx.params;
@ -358,7 +358,7 @@ class interfaceController extends baseController {
let validParams = Object.assign({}, params)
let validResult = yapi.commons.validateParams(this.schemaMap['up'], validParams);
if (validResult.valid) {
let data = {};
let data = Object.assign({}, ctx);
data.params = validParams;
if(params.res_body_is_json_schema && params.dataSync === 'good'){
@ -624,7 +624,6 @@ class interfaceController extends baseController {
* @returns {Object}
* @example ./api/interface/up.json
*/
async up(ctx) {
let params = ctx.params;
@ -1022,7 +1021,6 @@ class interfaceController extends baseController {
* @returns {Object}
* @example ./api/interface/getCatMenu
*/
async getCatMenu(ctx) {
let project_id = ctx.params.project_id;
@ -1117,7 +1115,6 @@ class interfaceController extends baseController {
* @returns {Object}
* @example
*/
async upIndex(ctx) {
try {
let params = ctx.request.body;
@ -1151,7 +1148,6 @@ class interfaceController extends baseController {
* @returns {Object}
* @example
*/
async upCatIndex(ctx) {
try {
let params = ctx.request.body;
@ -1180,7 +1176,7 @@ class interfaceController extends baseController {
let required = ctx.request.body.required;
let res = yapi.commons.schemaToJson(schema, {
alwaysFakeOptionals: _.isUndefined(required) ? true : require
alwaysFakeOptionals: _.isUndefined(required) ? true : required
});
// console.log('res',res)
return (ctx.body = res);

@ -590,6 +590,7 @@ class projectController extends baseController {
} else {
follow = follow.map(item => {
item = item.toObject();
item._id = item.projectid
item.follow = true;
return item;
});

@ -31,6 +31,7 @@ class userController extends baseController {
//登录
let userInst = yapi.getInst(userModel); //创建user实体
let email = ctx.request.body.email;
email = (email || '').trim();
let password = ctx.request.body.password;
if (!email) {
@ -410,6 +411,10 @@ class userController extends baseController {
let userInst = yapi.getInst(userModel);
let id = ctx.request.query.id;
if (this.getRole() !== 'admin' && id != this.getUid()) {
return (ctx.body = yapi.commons.resReturn(null, 401, '没有权限'));
}
if (!id) {
return (ctx.body = yapi.commons.resReturn(null, 400, 'uid不能为空'));
}

@ -130,7 +130,7 @@ function mockValidator(interfaceData, ctx) {
if (noRequiredArr.length > 0 || (validResult && !validResult.valid)) {
let message = `错误信息:`;
message += noRequiredArr.length > 0 ? `缺少必须字段 ${noRequiredArr.join(',')} ` : '';
message += validResult && !validResult.valid ? `shema 验证请求参数 ${validResult.message}` : '';
message += validResult && !validResult.valid ? `schema 验证请求参数 ${validResult.message}` : '';
return {
valid: false,

@ -13,6 +13,7 @@ const json5 = require('json5');
const _ = require('underscore');
const Ajv = require('ajv');
const Mock = require('mockjs');
const sandboxFn = require('./sandbox')
@ -22,10 +23,10 @@ const jsf = require('json-schema-faker');
const { schemaValidator } = require('../../common/utils');
const http = require('http');
jsf.extend ('mock', function () {
jsf.extend('mock', function () {
return {
mock: function (xx) {
return Mock.mock (xx);
return Mock.mock(xx);
}
};
});
@ -45,9 +46,9 @@ const defaultOptions = {
// });
// });
exports.schemaToJson = function(schema, options = {}) {
exports.schemaToJson = function (schema, options = {}) {
Object.assign(options, defaultOptions);
jsf.option(options);
let result;
try {
@ -183,7 +184,7 @@ exports.sendMail = (options, cb) => {
cb =
cb ||
function(err) {
function (err) {
if (err) {
yapi.commons.log('send mail ' + options.to + ' error,' + err.message, 'error');
} else {
@ -253,7 +254,7 @@ exports.handleVarPath = (pathname, params) => {
}
}
}
pathname.replace(/\{(.+?)\}/g, function(str, match) {
pathname.replace(/\{(.+?)\}/g, function (str, match) {
insertParams(match);
});
};
@ -281,15 +282,18 @@ exports.verifyPath = path => {
* a = {a: 2}
*/
exports.sandbox = (sandbox, script) => {
const vm = require('vm');
sandbox = sandbox || {};
script = new vm.Script(script);
const context = new vm.createContext(sandbox);
script.runInContext(context, {
timeout: 3000
});
return sandbox;
try {
const vm = require('vm');
sandbox = sandbox || {};
script = new vm.Script(script);
const context = new vm.createContext(sandbox);
script.runInContext(context, {
timeout: 3000
});
return sandbox
} catch (err) {
throw err
}
};
function trim(str) {
@ -421,7 +425,7 @@ exports.createAction = (router, baseurl, routerController, action, path, method,
await inst.init(ctx);
ctx.params = Object.assign({}, ctx.request.query, ctx.request.body, ctx.params);
if (inst.schemaMap && typeof inst.schemaMap === 'object' && inst.schemaMap[action]) {
let validResult = yapi.commons.validateParams(inst.schemaMap[action], ctx.params);
if (!validResult.valid) {
@ -453,7 +457,7 @@ function handleParamsValue(params, val) {
let value = {};
try {
params = params.toObject();
} catch (e) {}
} catch (e) { }
if (params.length === 0 || val.length === 0) {
return params;
}
@ -512,7 +516,7 @@ function convertString(variable) {
return variable.name + ': ' + variable.message;
}
try {
if(variable && typeof variable === 'string'){
if (variable && typeof variable === 'string') {
return variable;
}
return JSON.stringify(variable, null, ' ');
@ -541,39 +545,39 @@ exports.runCaseScript = async function runCaseScript(params, colId, interfaceId)
let result = {};
try {
if(colData.checkHttpCodeIs200){
if (colData.checkHttpCodeIs200) {
let status = +params.response.status;
if(status !== 200){
if (status !== 200) {
throw ('Http status code 不是 200请检查(该规则来源于于 [测试集->通用规则配置] )')
}
}
if(colData.checkResponseField.enable){
if(params.response.body[colData.checkResponseField.name] != colData.checkResponseField.value){
if (colData.checkResponseField.enable) {
if (params.response.body[colData.checkResponseField.name] != colData.checkResponseField.value) {
throw (`返回json ${colData.checkResponseField.name} 值不是${colData.checkResponseField.value},请检查(该规则来源于于 [测试集->通用规则配置] )`)
}
}
if(colData.checkResponseSchema){
if (colData.checkResponseSchema) {
const interfaceInst = yapi.getInst(interfaceModel);
let interfaceData = await interfaceInst.get(interfaceId);
if(interfaceData.res_body_is_json_schema && interfaceData.res_body){
if (interfaceData.res_body_is_json_schema && interfaceData.res_body) {
let schema = JSON.parse(interfaceData.res_body);
let result = schemaValidator(schema, context.body)
if(!result.valid){
if (!result.valid) {
throw (`返回Json 不符合 response 定义的数据结构,原因: ${result.message}
数据结构如下
${JSON.stringify(schema,null,2)}`)
${JSON.stringify(schema, null, 2)}`)
}
}
}
if(colData.checkScript.enable){
if (colData.checkScript.enable) {
let globalScript = colData.checkScript.content;
// script 是断言
if (globalScript) {
logs.push('执行脚本:' + globalScript)
result = yapi.commons.sandbox(context, globalScript);
result = await sandboxFn(context, globalScript);
}
}
@ -582,7 +586,7 @@ ${JSON.stringify(schema,null,2)}`)
// script 是断言
if (script) {
logs.push('执行脚本:' + script)
result = yapi.commons.sandbox(context, script);
result = await sandboxFn(context, script);
}
result.logs = logs;
return yapi.commons.resReturn(result);
@ -610,7 +614,7 @@ exports.getUserdata = async function getUserdata(uid, role) {
};
// 处理mockJs脚本
exports.handleMockScript = function(script, context) {
exports.handleMockScript = async function (script, context) {
let sandbox = {
header: context.ctx.header,
query: context.ctx.query,
@ -625,11 +629,11 @@ exports.handleMockScript = function(script, context) {
sandbox.cookie = {};
context.ctx.header.cookie &&
context.ctx.header.cookie.split(';').forEach(function(Cookie) {
context.ctx.header.cookie.split(';').forEach(function (Cookie) {
var parts = Cookie.split('=');
sandbox.cookie[parts[0].trim()] = (parts[1] || '').trim();
});
sandbox = yapi.commons.sandbox(sandbox, script);
sandbox = await sandboxFn(sandbox, script);
sandbox.delay = isNaN(sandbox.delay) ? 0 : +sandbox.delay;
context.mockJson = sandbox.mockJson;
@ -640,8 +644,8 @@ exports.handleMockScript = function(script, context) {
exports.createWebAPIRequest = function(ops) {
return new Promise(function(resolve, reject) {
exports.createWebAPIRequest = function (ops) {
return new Promise(function (resolve, reject) {
let req = '';
let http_client = http.request(
{
@ -650,25 +654,25 @@ exports.createWebAPIRequest = function(ops) {
port: ops.port,
path: ops.path
},
function(res) {
res.on('error', function(err) {
function (res) {
res.on('error', function (err) {
reject(err);
});
res.setEncoding('utf8');
if (res.statusCode != 200) {
reject({message: 'statusCode != 200'});
reject({ message: 'statusCode != 200' });
} else {
res.on('data', function(chunk) {
res.on('data', function (chunk) {
req += chunk;
});
res.on('end', function() {
res.on('end', function () {
resolve(req);
});
}
}
);
http_client.on('error', (e) => {
reject({message: `request error: ${e.message}`});
reject({ message: `request error: ${e.message}` });
});
http_client.end();
});

@ -19,7 +19,7 @@ function connect(callback) {
mongoose.set('useCreateIndex', true);
let config = yapi.WEBCONFIG;
let options = {useNewUrlParser: true, useCreateIndex: true};
let options = {useNewUrlParser: true, useCreateIndex: true, useUnifiedTopology: true};
if (config.db.user) {
options.user = config.db.user;

@ -114,8 +114,8 @@ exports.ldapQuery = (username, password) => {
const searchStandard = ldapLogin.searchStandard;
// 处理可以自定义filter
let customFilter;
if (/^&/gi.test(searchStandard)) {
customFilter = util.format(searchStandard, username);
if (/^(&|\|)/gi.test(searchStandard)) {
customFilter = searchStandard.replace(/%s/g,username);
} else {
customFilter = `${searchStandard}=${username}`;
}

16
server/utils/sandbox.js Normal file

@ -0,0 +1,16 @@
const Safeify = require('safeify').default;
module.exports = async function sandboxFn(context, script) {
// 创建 safeify 实例
const safeVm = new Safeify({
timeout: 3000,
asyncTimeout: 60000
})
// 执行动态代码
const result = await safeVm.run(script, context)
// 释放资源
safeVm.destroy()
return result
}

@ -1 +1 @@
window.WEBPACK_ASSETS = {"index.js":{"js":"index@8bf0bd2e360ca37a96c8.js","css":"index@8bf0bd2e360ca37a96c8.css"},"lib":{"js":"lib@aaed0f9bfcc4ff921c5a.js"},"lib2":{"js":"lib2@819909a89ca45b94d9bf.js"},"lib3":{"js":"lib3@93b22d7460620277a5da.js"},"manifest":{"js":"manifest@f2f4bd774d6c221b3d5f.js"}}
window.WEBPACK_ASSETS = {"index.js":{"js":"index@4df3f8796e0eea779ba6.js","css":"index@4df3f8796e0eea779ba6.css"},"lib":{"js":"lib@aaed0f9bfcc4ff921c5a.js"},"lib2":{"js":"lib2@819909a89ca45b94d9bf.js"},"lib3":{"js":"lib3@93b22d7460620277a5da.js"},"manifest":{"js":"manifest@f2f4bd774d6c221b3d5f.js"}}

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.