feat: 默认值系统

pull/635/head
bigfengyu 5 years ago
parent 08c17f9228
commit 4965cc445d

@ -143,7 +143,6 @@ npm run check
``` ```
#### 启动开发模式的服务器 监视并在发生代码变更时自动重启 #### 启动开发模式的服务器 监视并在发生代码变更时自动重启
```bash ```bash
npm run dev npm run dev
``` ```

@ -0,0 +1,2 @@
ALTER TABLE `Properties`
MODIFY COLUMN `type` enum('String','Number','Boolean','Object','Array','Function','RegExp','Null') NOT NULL;

@ -0,0 +1,11 @@
ALTER TABLE repositories_collaborators
DROP COLUMN createdat ;
ALTER TABLE repositories_collaborators
DROP COLUMN updatedat ;
ALTER TABLE repositories_members
DROP COLUMN createdat ;
ALTER TABLE repositories_members
DROP COLUMN updatedat ;

@ -0,0 +1,5 @@
ALTER TABLE `properties`
ADD COLUMN `pos` INT(10) NULL DEFAULT 2;
ALTER TABLE `interfaces`
ADD COLUMN `status` INT(10) NULL DEFAULT 200;

@ -0,0 +1,2 @@
ALTER TABLE Interfaces
MODIFY COLUMN `method` VARCHAR(256) NOT NULL;

@ -0,0 +1,2 @@
ALTER TABLE `Properties`
ADD COLUMN `required` TINYINT(1) NOT NULL DEFAULT 0;

@ -0,0 +1,11 @@
CREATE TABLE `default_val` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`createdat` datetime NOT NULL COMMENT '创建时间',
`updatedat` datetime NOT NULL COMMENT '修改时间',
`name` varchar(256) NOT NULL COMMENT '名字',
`rule` varchar(512) NOT NULL COMMENT '规则',
`value` text NOT NULL COMMENT '',
`repositoryid` bigint unsigned NOT NULL COMMENT 'FK',
`deletedat` datetime NOT NULL COMMENT '删除时间',
PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET=utf8mb4 COMMENT='默认值';

@ -23,78 +23,79 @@
"dependencies": { "dependencies": {
"@types/treeify": "^1.0.0", "@types/treeify": "^1.0.0",
"chalk": "^2.4.2", "chalk": "^2.4.2",
"cross-env": "^5.2.0", "cross-env": "^6.0.3",
"graceful": "^1.0.2", "graceful": "^1.0.2",
"is-md5": "^0.0.2", "is-md5": "^0.0.2",
"js-beautify": "^1.10.0", "js-beautify": "^1.10.2",
"kcors": "^2.2.2", "kcors": "^2.2.2",
"koa": "^2.7.0", "koa": "^2.11.0",
"koa-body": "^4.1.0", "koa-body": "^4.1.1",
"koa-generic-session": "^2.0.1", "koa-generic-session": "^2.0.1",
"koa-logger": "^3.2.0", "koa-logger": "^3.2.1",
"koa-redis": "^4.0.0", "koa-redis": "^4.0.0",
"koa-router": "^7.4.0", "koa-router": "^7.4.0",
"koa-send": "^5.0.0", "koa-send": "^5.0.0",
"koa-static": "^5.0.0", "koa-static": "^5.0.0",
"lodash": "^4.17.11", "lodash": "^4.17.15",
"mariadb": "^2.1.2",
"md5": "^2.2.1", "md5": "^2.2.1",
"mockjs": "^1.0.1-beta3", "mockjs": "1.1.0",
"moment": "^2.24.0", "moment": "^2.24.0",
"mysql": "^2.17.1", "mysql": "^2.17.1",
"mysql2": "^1.6.5", "mysql2": "^2.0.0",
"nanoid": "^2.1.6", "nanoid": "^2.1.6",
"node-fetch": "^2.6.0", "node-fetch": "^2.6.0",
"node-print": "0.0.4", "node-print": "0.0.4",
"node-schedule": "^1.3.2", "node-schedule": "^1.3.2",
"nodemailer": "^6.2.1", "nodemailer": "^6.2.1",
"notevil": "^1.3.1", "notevil": "^1.3.2",
"path-to-regexp": "^3.0.0", "path-to-regexp": "^3.1.0",
"redis": "^2.8.0", "redis": "^2.8.0",
"reflect-metadata": "^0.1.13", "reflect-metadata": "^0.1.13",
"request": "^2.88.0", "request": "^2.88.0",
"request-promise": "^4.2.4", "request-promise": "^4.2.5",
"sequelize": "^5.10.1", "sequelize": "^5.21.2",
"sequelize-typescript": "^1.0.0-beta.3", "sequelize-typescript": "^1.0.0",
"svg-captcha": "^1.4.0", "svg-captcha": "^1.4.0",
"treeify": "^1.1.0", "treeify": "^1.1.0",
"underscore": "^1.9.1", "underscore": "^1.9.1",
"urllib": "^2.34.0" "urllib": "^2.34.1"
}, },
"devDependencies": { "devDependencies": {
"@types/chai": "^4.1.7", "@types/chai": "^4.2.4",
"@types/kcors": "^2.2.3", "@types/kcors": "^2.2.3",
"@types/koa": "^2.0.51", "@types/koa": "^2.0.51",
"@types/koa-generic-session": "^1.0.2", "@types/koa-generic-session": "^1.0.3",
"@types/koa-logger": "^3.1.1", "@types/koa-logger": "^3.1.1",
"@types/koa-redis": "^3.0.2", "@types/koa-redis": "^3.0.3",
"@types/koa-router": "^7.0.40", "@types/koa-router": "^7.0.42",
"@types/koa-static": "^4.0.1", "@types/koa-static": "^4.0.1",
"@types/lodash": "^4.14.132", "@types/lodash": "^4.14.145",
"@types/md5": "^2.1.33", "@types/md5": "^2.1.33",
"@types/mocha": "^5.2.6", "@types/mocha": "^5.2.7",
"@types/mockjs": "^1.0.2", "@types/mockjs": "^1.0.2",
"@types/nanoid": "^2.1.0", "@types/nanoid": "^2.1.0",
"@types/node": "^12.0.3", "@types/node": "^12.12.6",
"@types/node-schedule": "^1.2.3", "@types/node-schedule": "^1.2.4",
"@types/nodemailer": "^6.2.0", "@types/nodemailer": "^6.2.2",
"@types/redis": "^2.8.13", "@types/redis": "^2.8.14",
"@types/request": "^2.48.1", "@types/request": "^2.48.3",
"@types/request-promise": "^4.1.44", "@types/request-promise": "^4.1.44",
"@types/sequelize": "^4.28.4", "@types/sequelize": "^4.28.6",
"@types/underscore": "^1.8.18", "@types/underscore": "^1.9.3",
"babel-eslint": "^10.0.1", "babel-eslint": "^10.0.3",
"chai": "^4.2.0", "chai": "^4.2.0",
"mocha": "^6.1.4", "mocha": "^6.2.2",
"nodemon": "^1.19.1", "nodemon": "^1.19.4",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"nyc": "^14.1.1", "nyc": "^14.1.1",
"pre-commit": "^1.2.2", "pre-commit": "^1.2.2",
"rimraf": "^2.6.3", "rimraf": "^3.0.0",
"source-map-support": "^0.5.12", "source-map-support": "^0.5.16",
"standard": "^12.0.1", "standard": "^14.3.1",
"supertest": "^4.0.2", "supertest": "^4.0.2",
"tslint": "^5.16.0", "tslint": "^5.20.1",
"typescript": "^3.5.1" "typescript": "^3.7.2"
}, },
"pre-commit": [ "pre-commit": [
"check" "check"

@ -1,6 +1,6 @@
import { IConfigOptions } from "../types" import { IConfigOptions } from "../types"
let config: IConfigOptions = { const config: IConfigOptions = {
version: 'v2.8.0', version: 'v2.8.0',
serve: { serve: {
port: (process.env.SERVE_PORT && parseInt(process.env.SERVE_PORT)) || 8080, port: (process.env.SERVE_PORT && parseInt(process.env.SERVE_PORT)) || 8080,
@ -12,17 +12,20 @@ let config: IConfigOptions = {
}, },
db: { db: {
dialect: 'mysql', dialect: 'mysql',
host: process.env.MYSQL_URL || 'localhost', host: process.env.MYSQL_URL ?? 'localhost',
port: (process.env.MYSQL_PORT && parseInt(process.env.MYSQL_PORT)) || 3306, port: (process.env.MYSQL_PORT && parseInt(process.env.MYSQL_PORT)) || 3306,
username: process.env.MYSQL_USERNAME || 'root', username: process.env.MYSQL_USERNAME ?? 'root',
password: process.env.MYSQL_PASSWD || '', password: process.env.MYSQL_PASSWD ?? '29837DF983(*&34kfjD(*3kjf(',
database: process.env.MYSQL_SCHEMA || 'RAP2_DELOS_APP', database: process.env.MYSQL_SCHEMA ?? 'RAP2_DELOS_APP',
pool: { pool: {
max: 5, max: 5,
min: 0, min: 0,
idle: 10000, idle: 10000,
}, },
logging: false, logging: false,
dialectOptions: {
connectTimeout: 20000,
},
}, },
redis: {}, redis: {},
mail: { mail: {

@ -0,0 +1,27 @@
import { Table, Column, Model, AutoIncrement, PrimaryKey, ForeignKey } from 'sequelize-typescript'
import { Repository } from '../../models'
@Table({ paranoid: true, freezeTableName: false, timestamps: true, tableName: 'default_val' })
export default class DefaultVal extends Model<DefaultVal> {
@PrimaryKey
@AutoIncrement
@Column
id: number
@Column
name: string
@Column
rule: string
@Column
value: string
@ForeignKey(() => Repository)
@Column
repositoryId: number
}

@ -10,3 +10,4 @@ export { default as User } from './bo/user'
export { default as OrganizationsMembers } from './bo/organizationsMembers' export { default as OrganizationsMembers } from './bo/organizationsMembers'
export { default as RepositoriesCollaborators } from './bo/repositoriesCollaborators' export { default as RepositoriesCollaborators } from './bo/repositoriesCollaborators'
export { default as RepositoriesMembers } from './bo/repositoriesMembers' export { default as RepositoriesMembers } from './bo/repositoriesMembers'
export { default as DefaultVal } from './bo/defaultVal'

@ -20,11 +20,13 @@ const sequelize = new Sequelize({
port: config.db.port, port: config.db.port,
pool: config.db.pool, pool: config.db.pool,
logging: config.db.logging ? logging : false, logging: config.db.logging ? logging : false,
dialectOptions: config.db.dialectOptions,
}) })
sequelize.addModels([__dirname + '/bo']) sequelize.addModels([__dirname + '/bo'])
sequelize.authenticate() sequelize.authenticate()
.then((/* err */) => { .then((/* err */) => {
sequelize.sync()
console.log('----------------------------------------') console.log('----------------------------------------')
console.log('DATABASE √') console.log('DATABASE √')
console.log(' HOST %s', config.db.host) console.log(' HOST %s', config.db.host)

@ -1,5 +1,5 @@
import router from './router' import router from './router'
import { Repository, Interface, Property } from '../models' import { Repository, Interface, Property, DefaultVal } from '../models'
import { QueryInclude } from '../models' import { QueryInclude } from '../models'
import Tree from './utils/tree' import Tree from './utils/tree'
import urlUtils from './utils/url' import urlUtils from './utils/url'
@ -269,10 +269,26 @@ router.all('/app/mock/:repositoryId(\\d+)/:url(.+)', async (ctx) => {
} }
let interfaceId = itf.id let interfaceId = itf.id
let properties: any = await Property.findAll({ let properties = await Property.findAll({
attributes, attributes,
where: { interfaceId, scope: 'response' }, where: { interfaceId, scope: 'response' },
}) })
// default values override
const defaultVals = await DefaultVal.findAll({ where: { repositoryId } })
const defaultValsMap: {[key: string]: DefaultVal} = {}
for (const dv of defaultVals) {
defaultValsMap[dv.name] = dv
}
for (const p of properties) {
const dv = defaultValsMap[p.name]
if (!p.value && !p.rule && dv) {
p.value = dv.value
p.rule = dv.rule
}
}
// check required // check required
if (~['GET', 'POST'].indexOf(method)) { if (~['GET', 'POST'].indexOf(method)) {
let requiredProperties = await Property.findAll({ let requiredProperties = await Property.findAll({
@ -310,7 +326,10 @@ router.all('/app/mock/:repositoryId(\\d+)/:url(.+)', async (ctx) => {
requestProperties = requestProperties.map((item: any) => item.toJSON()) requestProperties = requestProperties.map((item: any) => item.toJSON())
let requestData = Tree.ArrayToTreeToTemplateToData(requestProperties) let requestData = Tree.ArrayToTreeToTemplateToData(requestProperties)
Object.assign(requestData, { ...ctx.params, ...ctx.query, ...ctx.body }) Object.assign(requestData, { ...ctx.params, ...ctx.query, ...ctx.body })
const data = Tree.ArrayToTreeToTemplateToData(properties, requestData) let data = Tree.ArrayToTreeToTemplateToData(properties, requestData)
if (data.__root__) {
data = data.__root__
}
ctx.type = 'json' ctx.type = 'json'
ctx.status = itf.status ctx.status = itf.status
ctx.body = JSON.stringify(data, undefined, 2) ctx.body = JSON.stringify(data, undefined, 2)

@ -2,7 +2,7 @@
import router from './router' import router from './router'
import * as _ from 'underscore' import * as _ from 'underscore'
import Pagination from './utils/pagination' import Pagination from './utils/pagination'
import { User, Organization, Repository, Module, Interface, Property, QueryInclude, Logger } from '../models' import { User, Organization, Repository, Module, Interface, Property, QueryInclude, Logger, DefaultVal } from '../models'
import Tree from './utils/tree' import Tree from './utils/tree'
import { AccessUtils, ACCESS_TYPE } from './utils/access' import { AccessUtils, ACCESS_TYPE } from './utils/access'
import * as Consts from './utils/const' import * as Consts from './utils/const'
@ -132,6 +132,7 @@ router.get('/repository/owned', isLoggedIn, async (ctx) => {
pagination: undefined, pagination: undefined,
} }
}) })
router.get('/repository/joined', isLoggedIn, async (ctx) => { router.get('/repository/joined', isLoggedIn, async (ctx) => {
let where: any = {} let where: any = {}
let { name } = ctx.query let { name } = ctx.query
@ -269,6 +270,7 @@ router.post('/repository/create', isLoggedIn, async (ctx, next) => {
repositoryId: ctx.body.data.id, repositoryId: ctx.body.data.id,
}) })
}) })
router.post('/repository/update', isLoggedIn, async (ctx, next) => { router.post('/repository/update', isLoggedIn, async (ctx, next) => {
const body = Object.assign({}, ctx.request.body) const body = Object.assign({}, ctx.request.body)
if (!await AccessUtils.canUserAccess(ACCESS_TYPE.REPOSITORY, ctx.session.id, body.id)) { if (!await AccessUtils.canUserAccess(ACCESS_TYPE.REPOSITORY, ctx.session.id, body.id)) {
@ -336,6 +338,7 @@ router.post('/repository/update', isLoggedIn, async (ctx, next) => {
await Logger.create({ creatorId, userId, type: 'exit', repositoryId: id }) await Logger.create({ creatorId, userId, type: 'exit', repositoryId: id })
} }
}) })
router.post('/repository/transfer', isLoggedIn, async (ctx) => { router.post('/repository/transfer', isLoggedIn, async (ctx) => {
let { id, ownerId, organizationId } = ctx.request.body let { id, ownerId, organizationId } = ctx.request.body
if (!await AccessUtils.canUserAccess(ACCESS_TYPE.ORGANIZATION, ctx.session.id, organizationId)) { if (!await AccessUtils.canUserAccess(ACCESS_TYPE.ORGANIZATION, ctx.session.id, organizationId)) {
@ -353,6 +356,7 @@ router.post('/repository/transfer', isLoggedIn, async (ctx) => {
data: result[0], data: result[0],
} }
}) })
router.get('/repository/remove', isLoggedIn, async (ctx, next) => { router.get('/repository/remove', isLoggedIn, async (ctx, next) => {
const id = +ctx.query.id const id = +ctx.query.id
if (!await AccessUtils.canUserAccess(ACCESS_TYPE.REPOSITORY, ctx.session.id, id)) { if (!await AccessUtils.canUserAccess(ACCESS_TYPE.REPOSITORY, ctx.session.id, id)) {
@ -394,6 +398,7 @@ router.post('/repository/lock', isLoggedIn, async (ctx) => {
}) })
ctx.body = { data: result[0] } ctx.body = { data: result[0] }
}) })
router.post('/repository/unlock', async (ctx) => { router.post('/repository/unlock', async (ctx) => {
if (!ctx.session.id) { if (!ctx.session.id) {
ctx.body = { data: 0 } ctx.body = { data: 0 }
@ -413,6 +418,7 @@ router.get('/module/count', async (ctx) => {
data: await Module.count(), data: await Module.count(),
} }
}) })
router.get('/module/list', async (ctx) => { router.get('/module/list', async (ctx) => {
let where: any = {} let where: any = {}
let { repositoryId, name } = ctx.query let { repositoryId, name } = ctx.query
@ -425,6 +431,7 @@ router.get('/module/list', async (ctx) => {
}), }),
} }
}) })
router.get('/module/get', async (ctx) => { router.get('/module/get', async (ctx) => {
ctx.body = { ctx.body = {
data: await Module.findByPk(ctx.query.id, { data: await Module.findByPk(ctx.query.id, {
@ -432,6 +439,7 @@ router.get('/module/get', async (ctx) => {
}) })
} }
}) })
router.post('/module/create', isLoggedIn, async (ctx, next) => { router.post('/module/create', isLoggedIn, async (ctx, next) => {
let creatorId = ctx.session.id let creatorId = ctx.session.id
let body = Object.assign(ctx.request.body, { creatorId }) let body = Object.assign(ctx.request.body, { creatorId })
@ -451,6 +459,7 @@ router.post('/module/create', isLoggedIn, async (ctx, next) => {
moduleId: mod.id, moduleId: mod.id,
}) })
}) })
router.post('/module/update', isLoggedIn, async (ctx, next) => { router.post('/module/update', isLoggedIn, async (ctx, next) => {
const { id, name, description } = ctx.request.body const { id, name, description } = ctx.request.body
if (!await AccessUtils.canUserAccess(ACCESS_TYPE.MODULE, ctx.session.id, +id)) { if (!await AccessUtils.canUserAccess(ACCESS_TYPE.MODULE, ctx.session.id, +id)) {
@ -478,6 +487,7 @@ router.post('/module/update', isLoggedIn, async (ctx, next) => {
moduleId: mod.id, moduleId: mod.id,
}) })
}) })
router.get('/module/remove', isLoggedIn, async (ctx, next) => { router.get('/module/remove', isLoggedIn, async (ctx, next) => {
let { id } = ctx.query let { id } = ctx.query
if (!await AccessUtils.canUserAccess(ACCESS_TYPE.MODULE, ctx.session.id, +id)) { if (!await AccessUtils.canUserAccess(ACCESS_TYPE.MODULE, ctx.session.id, +id)) {
@ -502,6 +512,7 @@ router.get('/module/remove', isLoggedIn, async (ctx, next) => {
moduleId: mod.id, moduleId: mod.id,
}) })
}) })
router.post('/module/sort', isLoggedIn, async (ctx) => { router.post('/module/sort', isLoggedIn, async (ctx) => {
let { ids } = ctx.request.body let { ids } = ctx.request.body
let counter = 1 let counter = 1
@ -519,12 +530,12 @@ router.post('/module/sort', isLoggedIn, async (ctx) => {
} }
}) })
//
router.get('/interface/count', async (ctx) => { router.get('/interface/count', async (ctx) => {
ctx.body = { ctx.body = {
data: await Interface.count(), data: await Interface.count(),
} }
}) })
router.get('/interface/list', async (ctx) => { router.get('/interface/list', async (ctx) => {
let where: any = {} let where: any = {}
let { repositoryId, moduleId, name } = ctx.query let { repositoryId, moduleId, name } = ctx.query
@ -542,6 +553,40 @@ router.get('/interface/list', async (ctx) => {
}), }),
} }
}) })
router.get('/repository/defaultVal/get/:id', async (ctx) => {
const repositoryId: number = ctx.params.id
ctx.body = {
data: await DefaultVal.findAll({ where: { repositoryId } })
}
})
router.post('/repository/defaultVal/update/:id', async (ctx) => {
const repositoryId: number = ctx.params.id
if (!await AccessUtils.canUserAccess(ACCESS_TYPE.REPOSITORY, ctx.session.id, repositoryId)) {
ctx.body = Consts.COMMON_ERROR_RES.ACCESS_DENY
return
}
const list = ctx.request.body.list
if (!(repositoryId > 0) || !list) {
ctx.body = Consts.COMMON_ERROR_RES.ERROR_PARAMS
return
}
await DefaultVal.destroy({
where: { repositoryId }
})
for (const item of list) {
await DefaultVal.create({
...item,
repositoryId,
})
}
ctx.body = {
isOk: true,
}
})
router.get('/interface/get', async (ctx) => { router.get('/interface/get', async (ctx) => {
let { id } = ctx.query let { id } = ctx.query
@ -555,7 +600,6 @@ router.get('/interface/get', async (ctx) => {
let itf = await Interface.findByPk(id, { let itf = await Interface.findByPk(id, {
attributes: { exclude: [] }, attributes: { exclude: [] },
include: [QueryInclude.Properties]
}) })
if (!itf) { if (!itf) {
@ -563,6 +607,7 @@ router.get('/interface/get', async (ctx) => {
isOk: false, isOk: false,
errMsg: `没有找到 id 为 ${id} 的接口` errMsg: `没有找到 id 为 ${id} 的接口`
} }
return
} }
if ( if (
@ -578,10 +623,20 @@ router.get('/interface/get', async (ctx) => {
const itfJSON: { [k: string]: any } = itf.toJSON() const itfJSON: { [k: string]: any } = itf.toJSON()
itfJSON['treeProperties'] = Tree.ArrayToTree(itf.properties).children let scopes = ['request', 'response']
for (let i = 0; i < scopes.length; i++) {
let properties: any = await Property.findAll({
attributes: { exclude: [] },
where: { interfaceId: itf.id, scope: scopes[i] }
})
properties = properties.map((item: any) => item.toJSON())
itfJSON[scopes[i] + 'Properties'] = Tree.ArrayToTree(properties).children
}
ctx.type = 'json' ctx.type = 'json'
ctx.body = Tree.stringifyWithFunctonAndRegExp({ data: itfJSON }) ctx.body = Tree.stringifyWithFunctonAndRegExp({ data: itfJSON })
}) })
router.post('/interface/create', isLoggedIn, async (ctx, next) => { router.post('/interface/create', isLoggedIn, async (ctx, next) => {
let creatorId = ctx.session.id let creatorId = ctx.session.id
let body = Object.assign(ctx.request.body, { creatorId }) let body = Object.assign(ctx.request.body, { creatorId })
@ -784,8 +839,8 @@ router.post('/interface/unlock', async (ctx) => {
// tslint:disable-next-line:no-null-keyword // tslint:disable-next-line:no-null-keyword
lockerId: null, lockerId: null,
}, { }, {
where: { id } where: { id }
}) })
ctx.body = { ctx.body = {
data: { data: {

@ -5,7 +5,7 @@
"moduleResolution": "node", "moduleResolution": "node",
"experimentalDecorators": true, "experimentalDecorators": true,
"emitDecoratorMetadata": true, "emitDecoratorMetadata": true,
"target": "esnext", "target": "es2019",
"removeComments": true, "removeComments": true,
"sourceMap": true, "sourceMap": true,
"watch": false, "watch": false,

Loading…
Cancel
Save