2017-09-03 08:43:13 +08:00
|
|
|
|
const fs = require('fs-extra');
|
|
|
|
|
const path = require('path');
|
|
|
|
|
const yapi = require('../yapi.js');
|
|
|
|
|
const sha1 = require('sha1');
|
|
|
|
|
const logModel = require('../models/log.js');
|
|
|
|
|
const json5 = require('json5');
|
2017-12-07 10:05:16 +08:00
|
|
|
|
const _ = require('underscore');
|
2017-12-15 10:49:48 +08:00
|
|
|
|
const Ajv = require('ajv');
|
|
|
|
|
const ajv = new Ajv({
|
2018-01-03 13:58:39 +08:00
|
|
|
|
allErrors: true,
|
|
|
|
|
coerceTypes: true,
|
|
|
|
|
useDefaults: true,
|
|
|
|
|
removeAdditional: true
|
2017-12-15 10:49:48 +08:00
|
|
|
|
});
|
|
|
|
|
var localize = require('ajv-i18n');
|
|
|
|
|
|
|
|
|
|
const ejs = require('easy-json-schema');
|
2017-07-03 16:16:05 +08:00
|
|
|
|
|
2017-07-18 15:31:41 +08:00
|
|
|
|
exports.resReturn = (data, num, errmsg) => {
|
2018-01-03 13:58:39 +08:00
|
|
|
|
num = num || 0;
|
2017-07-26 22:03:18 +08:00
|
|
|
|
|
2018-01-03 13:58:39 +08:00
|
|
|
|
return {
|
|
|
|
|
errcode: num,
|
|
|
|
|
errmsg: errmsg || '成功!',
|
|
|
|
|
data: data
|
|
|
|
|
};
|
2017-07-26 22:03:18 +08:00
|
|
|
|
};
|
2017-07-03 16:16:05 +08:00
|
|
|
|
|
2017-07-18 15:31:41 +08:00
|
|
|
|
exports.log = (msg, type) => {
|
2018-01-03 13:58:39 +08:00
|
|
|
|
if (!msg) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type = type || 'log';
|
|
|
|
|
|
|
|
|
|
let f;
|
|
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
|
case 'log':
|
|
|
|
|
f = console.log; // eslint-disable-line
|
|
|
|
|
break;
|
|
|
|
|
case 'warn':
|
|
|
|
|
f = console.warn; // eslint-disable-line
|
|
|
|
|
break;
|
|
|
|
|
case 'error':
|
|
|
|
|
f = console.error; // eslint-disable-line
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
f = console.log; // eslint-disable-line
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
f(type + ':', msg);
|
|
|
|
|
|
|
|
|
|
let date = new Date();
|
|
|
|
|
let year = date.getFullYear();
|
|
|
|
|
let month = date.getMonth() + 1;
|
|
|
|
|
|
|
|
|
|
let logfile = path.join(yapi.WEBROOT_LOG, year + '-' + month + '.log');
|
|
|
|
|
|
|
|
|
|
if (typeof msg === 'object') {
|
|
|
|
|
if (msg instanceof Error) msg = msg.message;
|
|
|
|
|
else msg = JSON.stringify(msg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// let data = (new Date).toLocaleString() + '\t|\t' + type + '\t|\t' + msg + '\n';
|
|
|
|
|
let data = `[ ${(new Date).toLocaleString()} ] [ ${type} ] ${msg}\n`;
|
|
|
|
|
|
|
|
|
|
fs.writeFileSync(logfile, data, {
|
|
|
|
|
flag: 'a'
|
|
|
|
|
});
|
2017-07-26 22:03:18 +08:00
|
|
|
|
};
|
2017-07-03 16:16:05 +08:00
|
|
|
|
|
2017-07-18 15:31:41 +08:00
|
|
|
|
exports.fileExist = (filePath) => {
|
2018-01-03 13:58:39 +08:00
|
|
|
|
try {
|
|
|
|
|
return fs.statSync(filePath).isFile();
|
|
|
|
|
} catch (err) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2017-07-26 22:03:18 +08:00
|
|
|
|
};
|
2017-07-03 16:16:05 +08:00
|
|
|
|
|
2017-07-04 16:43:07 +08:00
|
|
|
|
exports.time = () => {
|
2018-01-03 13:58:39 +08:00
|
|
|
|
return Date.parse(new Date()) / 1000;
|
2017-07-26 22:03:18 +08:00
|
|
|
|
};
|
2017-07-04 16:43:07 +08:00
|
|
|
|
|
2017-07-18 15:31:41 +08:00
|
|
|
|
exports.fieldSelect = (data, field) => {
|
2018-01-03 13:58:39 +08:00
|
|
|
|
if (!data || !field || !Array.isArray(field)) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
2017-07-26 22:03:18 +08:00
|
|
|
|
|
2018-01-03 13:58:39 +08:00
|
|
|
|
var arr = {};
|
2017-07-26 22:03:18 +08:00
|
|
|
|
|
2018-01-03 13:58:39 +08:00
|
|
|
|
field.forEach((f) => {
|
|
|
|
|
(typeof data[f] !== 'undefined') && (arr[f] = data[f]);
|
|
|
|
|
});
|
2017-07-26 22:03:18 +08:00
|
|
|
|
|
2018-01-03 13:58:39 +08:00
|
|
|
|
return arr;
|
2017-07-26 22:03:18 +08:00
|
|
|
|
};
|
2017-07-10 11:56:53 +08:00
|
|
|
|
|
2017-07-18 15:31:41 +08:00
|
|
|
|
exports.rand = (min, max) => {
|
2018-01-03 13:58:39 +08:00
|
|
|
|
return Math.floor(Math.random() * (max - min) + min);
|
2017-07-26 22:03:18 +08:00
|
|
|
|
};
|
2017-07-10 11:56:53 +08:00
|
|
|
|
|
2017-07-18 15:31:41 +08:00
|
|
|
|
exports.json_parse = (json) => {
|
2018-01-03 13:58:39 +08:00
|
|
|
|
try {
|
|
|
|
|
return json5.parse(json);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
return json;
|
|
|
|
|
}
|
2017-07-26 22:03:18 +08:00
|
|
|
|
};
|
2017-07-11 12:12:43 +08:00
|
|
|
|
|
2017-07-18 15:31:41 +08:00
|
|
|
|
exports.randStr = () => {
|
2018-01-03 13:58:39 +08:00
|
|
|
|
return Math.random().toString(36).substr(2);
|
2017-07-26 22:03:18 +08:00
|
|
|
|
};
|
2018-01-03 13:58:39 +08:00
|
|
|
|
exports.getIp = (ctx) => {
|
|
|
|
|
let ip;
|
|
|
|
|
try {
|
2018-01-09 23:27:27 +08:00
|
|
|
|
ip = ctx.ip.match(/\d+.\d+.\d+.\d+/) ? ctx.ip.match(/\d+.\d+.\d+.\d+/)[0] : 'localhost';
|
2018-01-03 13:58:39 +08:00
|
|
|
|
} catch (e) {
|
|
|
|
|
ip = null;
|
|
|
|
|
}
|
|
|
|
|
return ip
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-11 12:12:43 +08:00
|
|
|
|
|
|
|
|
|
exports.generatePassword = (password, passsalt) => {
|
2018-01-03 13:58:39 +08:00
|
|
|
|
return sha1(password + sha1(passsalt));
|
2017-07-26 22:03:18 +08:00
|
|
|
|
};
|
2017-07-11 12:12:43 +08:00
|
|
|
|
|
|
|
|
|
exports.expireDate = (day) => {
|
2018-01-03 13:58:39 +08:00
|
|
|
|
let date = new Date();
|
|
|
|
|
date.setTime(date.getTime() + day * 86400000);
|
|
|
|
|
return date;
|
2017-07-26 22:03:18 +08:00
|
|
|
|
};
|
2017-07-11 16:50:17 +08:00
|
|
|
|
|
2017-07-18 15:31:41 +08:00
|
|
|
|
exports.sendMail = (options, cb) => {
|
2018-01-03 13:58:39 +08:00
|
|
|
|
if (!yapi.mail) return false;
|
|
|
|
|
options.subject = options.subject ? options.subject + '-YApi 平台' : 'YApi 平台';
|
2017-07-26 22:03:18 +08:00
|
|
|
|
|
2018-01-03 13:58:39 +08:00
|
|
|
|
cb = cb || function (err) {
|
|
|
|
|
if (err) {
|
|
|
|
|
yapi.commons.log('send mail ' + options.to + ' error,' + err.message, 'error');
|
2017-07-18 15:31:41 +08:00
|
|
|
|
|
2018-01-03 13:58:39 +08:00
|
|
|
|
} else {
|
|
|
|
|
yapi.commons.log('send mail ' + options.to + ' success');
|
2017-07-26 11:26:28 +08:00
|
|
|
|
}
|
2018-01-03 13:58:39 +08:00
|
|
|
|
};
|
2018-01-03 16:43:43 +08:00
|
|
|
|
|
2018-01-03 13:58:39 +08:00
|
|
|
|
try {
|
|
|
|
|
yapi.mail.sendMail({
|
|
|
|
|
from: yapi.WEBCONFIG.mail.from,
|
|
|
|
|
to: options.to,
|
|
|
|
|
subject: options.subject,
|
|
|
|
|
html: options.contents
|
|
|
|
|
}, cb);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
yapi.commons.log(e.message, 'error')
|
|
|
|
|
console.error(e.message); // eslint-disable-line
|
|
|
|
|
}
|
2017-07-26 22:03:18 +08:00
|
|
|
|
};
|
2017-07-14 16:41:14 +08:00
|
|
|
|
|
|
|
|
|
exports.validateSearchKeyword = keyword => {
|
2018-01-03 13:58:39 +08:00
|
|
|
|
if (/^\*|\?|\+|\$|\^|\\|\.$/.test(keyword)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2017-07-26 22:03:18 +08:00
|
|
|
|
|
2018-01-03 13:58:39 +08:00
|
|
|
|
return true;
|
2017-07-26 22:03:18 +08:00
|
|
|
|
};
|
2017-07-18 15:31:41 +08:00
|
|
|
|
|
|
|
|
|
exports.filterRes = (list, rules) => {
|
2018-01-03 13:58:39 +08:00
|
|
|
|
return list.map(item => {
|
|
|
|
|
let filteredRes = {};
|
|
|
|
|
|
|
|
|
|
rules.forEach(rule => {
|
|
|
|
|
if (typeof rule == 'string') {
|
|
|
|
|
filteredRes[rule] = item[rule];
|
|
|
|
|
} else if (typeof rule == 'object') {
|
|
|
|
|
filteredRes[rule.alias] = item[rule.key];
|
|
|
|
|
}
|
2017-07-26 22:03:18 +08:00
|
|
|
|
});
|
2018-01-03 13:58:39 +08:00
|
|
|
|
|
|
|
|
|
return filteredRes;
|
|
|
|
|
});
|
2017-07-26 22:03:18 +08:00
|
|
|
|
};
|
2017-07-24 11:24:08 +08:00
|
|
|
|
|
2018-01-03 13:58:39 +08:00
|
|
|
|
exports.handleVarPath = (pathname, params) => {
|
2017-12-07 10:05:16 +08:00
|
|
|
|
|
2018-01-03 13:58:39 +08:00
|
|
|
|
function insertParams(name) {
|
|
|
|
|
if (!_.find(params, { name: name })) {
|
|
|
|
|
params.push({
|
|
|
|
|
name: name,
|
|
|
|
|
desc: ''
|
|
|
|
|
})
|
2017-12-07 10:05:16 +08:00
|
|
|
|
}
|
2018-01-03 13:58:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!pathname) return;
|
|
|
|
|
if (pathname.indexOf(':') !== -1) {
|
|
|
|
|
let paths = pathname.split("/"), name, i;
|
|
|
|
|
for (i = 1; i < paths.length; i++) {
|
|
|
|
|
if (paths[i] && paths[i][0] === ':') {
|
|
|
|
|
name = paths[i].substr(1);
|
|
|
|
|
insertParams(name)
|
|
|
|
|
}
|
2017-12-07 10:05:16 +08:00
|
|
|
|
}
|
2018-01-03 13:58:39 +08:00
|
|
|
|
}
|
|
|
|
|
pathname.replace(/\{(.+?)\}/g, function (str, match) {
|
|
|
|
|
insertParams(match)
|
|
|
|
|
})
|
2017-12-07 10:05:16 +08:00
|
|
|
|
}
|
|
|
|
|
|
2017-10-19 15:59:14 +08:00
|
|
|
|
/**
|
|
|
|
|
* 验证一个 path 是否合法
|
2017-12-07 10:05:16 +08:00
|
|
|
|
* path第一位必需为 /, path 只允许由 字母数字-/_:.{}= 组成
|
2017-10-19 15:59:14 +08:00
|
|
|
|
*/
|
2017-07-24 11:24:08 +08:00
|
|
|
|
exports.verifyPath = (path) => {
|
2018-01-03 13:58:39 +08:00
|
|
|
|
if (/^\/[a-zA-Z0-9\-\/_:\.\{\}\=]*$/.test(path)) {
|
|
|
|
|
return true;
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2017-07-26 22:03:18 +08:00
|
|
|
|
};
|
2017-07-26 14:22:59 +08:00
|
|
|
|
|
2017-10-19 15:59:14 +08:00
|
|
|
|
/**
|
|
|
|
|
* 沙盒执行 js 代码
|
|
|
|
|
* @sandbox Object context
|
|
|
|
|
* @script String script
|
|
|
|
|
* @return sandbox
|
|
|
|
|
*
|
|
|
|
|
* @example let a = sandbox({a: 1}, 'a=2')
|
|
|
|
|
* a = {a: 2}
|
|
|
|
|
*/
|
2017-09-17 13:36:51 +08:00
|
|
|
|
exports.sandbox = (sandbox, script) => {
|
2018-01-03 13:58:39 +08:00
|
|
|
|
const vm = require('vm');
|
|
|
|
|
sandbox = sandbox || {};
|
|
|
|
|
script = new vm.Script(script);
|
|
|
|
|
const context = new vm.createContext(sandbox);
|
|
|
|
|
script.runInContext(context, {
|
|
|
|
|
timeout: 3000
|
|
|
|
|
});
|
|
|
|
|
return sandbox;
|
2017-09-17 13:36:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-26 14:22:59 +08:00
|
|
|
|
function trim(str) {
|
2018-01-03 13:58:39 +08:00
|
|
|
|
if (!str) {
|
|
|
|
|
return str;
|
|
|
|
|
}
|
2017-07-26 22:03:18 +08:00
|
|
|
|
|
2018-01-03 13:58:39 +08:00
|
|
|
|
str = str + '';
|
2017-07-26 22:03:18 +08:00
|
|
|
|
|
2018-01-03 13:58:39 +08:00
|
|
|
|
return str.replace(/(^\s*)|(\s*$)/g, '');
|
2017-07-26 14:22:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function ltrim(str) {
|
2018-01-03 13:58:39 +08:00
|
|
|
|
if (!str) {
|
|
|
|
|
return str;
|
|
|
|
|
}
|
2017-07-26 22:03:18 +08:00
|
|
|
|
|
2018-01-03 13:58:39 +08:00
|
|
|
|
str = str + '';
|
2017-07-26 22:03:18 +08:00
|
|
|
|
|
2018-01-03 13:58:39 +08:00
|
|
|
|
return str.replace(/(^\s*)/g, '');
|
2017-07-26 14:22:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function rtrim(str) {
|
2018-01-03 13:58:39 +08:00
|
|
|
|
if (!str) {
|
|
|
|
|
return str;
|
|
|
|
|
}
|
2017-07-26 22:03:18 +08:00
|
|
|
|
|
2018-01-03 13:58:39 +08:00
|
|
|
|
str = str + '';
|
2017-07-26 22:03:18 +08:00
|
|
|
|
|
2018-01-03 13:58:39 +08:00
|
|
|
|
return str.replace(/(\s*$)/g, '');
|
2017-07-26 14:22:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
exports.trim = trim;
|
|
|
|
|
exports.ltrim = ltrim;
|
|
|
|
|
exports.rtrim = rtrim;
|
|
|
|
|
|
2017-10-19 15:59:14 +08:00
|
|
|
|
/**
|
|
|
|
|
* 处理请求参数类型,String 字符串去除两边空格,Number 使用parseInt 转换为数字
|
|
|
|
|
* @params Object {a: ' ab ', b: ' 123 '}
|
|
|
|
|
* @keys Object {a: 'string', b: 'number'}
|
|
|
|
|
* @return Object {a: 'ab', b: 123}
|
|
|
|
|
*/
|
2017-07-26 14:22:59 +08:00
|
|
|
|
exports.handleParams = (params, keys) => {
|
2018-01-03 13:58:39 +08:00
|
|
|
|
if (!params || typeof params !== 'object' || !keys || typeof keys !== 'object') {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (var key in keys) {
|
|
|
|
|
var filter = keys[key];
|
|
|
|
|
if (params[key]) {
|
|
|
|
|
switch (filter) {
|
|
|
|
|
case 'string': params[key] = trim(params[key] + '');
|
|
|
|
|
break;
|
|
|
|
|
case 'number': params[key] = !isNaN(params[key]) ? parseInt(params[key], 10) : 0;
|
|
|
|
|
break;
|
|
|
|
|
default: params[key] = trim(params + '');
|
|
|
|
|
}
|
2017-07-26 14:22:59 +08:00
|
|
|
|
}
|
2018-01-03 13:58:39 +08:00
|
|
|
|
}
|
2017-07-26 22:03:18 +08:00
|
|
|
|
|
2018-01-03 13:58:39 +08:00
|
|
|
|
return params;
|
2017-08-16 17:12:01 +08:00
|
|
|
|
};
|
|
|
|
|
|
2018-01-03 13:58:39 +08:00
|
|
|
|
exports.validateParams = (schema, params) => {
|
|
|
|
|
schema = ejs(schema);
|
|
|
|
|
schema.additionalProperties = false;
|
|
|
|
|
const validate = ajv.compile(schema);
|
|
|
|
|
let valid = validate(params);
|
|
|
|
|
let message = '请求参数 ';
|
|
|
|
|
if (!valid) {
|
|
|
|
|
localize.zh(validate.errors);
|
|
|
|
|
message += ajv.errorsText(validate.errors, { separator: '\n' });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
valid: valid,
|
|
|
|
|
message: message
|
|
|
|
|
}
|
2017-12-15 10:49:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
2017-08-16 17:12:01 +08:00
|
|
|
|
|
|
|
|
|
exports.saveLog = (logData) => {
|
2018-01-03 13:58:39 +08:00
|
|
|
|
try {
|
|
|
|
|
let logInst = yapi.getInst(logModel);
|
|
|
|
|
let data = {
|
|
|
|
|
content: logData.content,
|
|
|
|
|
type: logData.type,
|
|
|
|
|
uid: logData.uid,
|
|
|
|
|
username: logData.username,
|
|
|
|
|
typeid: logData.typeid,
|
|
|
|
|
data: logData.data
|
|
|
|
|
};
|
|
|
|
|
logInst.save(data).then();
|
|
|
|
|
} catch (e) {
|
|
|
|
|
yapi.commons.log(e, 'error'); // eslint-disable-line
|
|
|
|
|
}
|
2017-08-16 17:12:01 +08:00
|
|
|
|
};
|
2017-11-15 12:37:23 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* @param {*} router router
|
|
|
|
|
* @param {*} baseurl base_url_path
|
|
|
|
|
* @param {*} routerController controller
|
|
|
|
|
* @param {*} path routerPath
|
|
|
|
|
* @param {*} method request_method , post get put delete ...
|
|
|
|
|
* @param {*} action controller action_name
|
|
|
|
|
* @param {*} ws enable ws
|
|
|
|
|
*/
|
|
|
|
|
exports.createAction = (router, baseurl, routerController, action, path, method, ws) => {
|
2018-01-03 13:58:39 +08:00
|
|
|
|
router[method](baseurl + path, async (ctx) => {
|
|
|
|
|
let inst = new routerController(ctx);
|
|
|
|
|
try {
|
|
|
|
|
await inst.init(ctx);
|
|
|
|
|
if (inst.schemaMap && typeof inst.schemaMap === 'object' && inst.schemaMap[action]) {
|
|
|
|
|
ctx.params = Object.assign({}, ctx.request.query, ctx.request.body, ctx.params);
|
|
|
|
|
let validResult = yapi.commons.validateParams(inst.schemaMap[action], ctx.params);
|
|
|
|
|
|
|
|
|
|
if (!validResult.valid) {
|
|
|
|
|
return ctx.body = yapi.commons.resReturn(null, 400, validResult.message);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (inst.$auth === true) {
|
|
|
|
|
await inst[action].call(inst, ctx);
|
|
|
|
|
} else {
|
|
|
|
|
if (ws === true) {
|
|
|
|
|
ctx.ws.send('请登录...');
|
|
|
|
|
} else {
|
|
|
|
|
ctx.body = yapi.commons.resReturn(null, 40011, '请登录...');
|
2017-11-15 12:37:23 +08:00
|
|
|
|
}
|
2018-01-03 13:58:39 +08:00
|
|
|
|
}
|
|
|
|
|
} catch (err) {
|
|
|
|
|
ctx.body = yapi.commons.resReturn(null, 40011, '服务器出错...');
|
|
|
|
|
yapi.commons.log(err, 'error')
|
|
|
|
|
}
|
2017-11-15 12:37:23 +08:00
|
|
|
|
|
2018-01-03 13:58:39 +08:00
|
|
|
|
});
|
2017-11-15 12:37:23 +08:00
|
|
|
|
}
|