generated from HeraldStudio/herald-webservice-template
-
Notifications
You must be signed in to change notification settings - Fork 1
/
repl.js
168 lines (151 loc) · 5.82 KB
/
repl.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
const vm = require('vm')
const qs = require('querystring')
const repl = require('repl')
const axios = require('axios')
const { config } = require('./app')
const prettyjson = require('prettyjson')
const oracle = require('./database/oracle')
const crypto = require('crypto')
const hash = value => {
return Buffer.from(crypto.createHash('sha256').update(value).digest()).toString('hex')
}
function isRecoverableError(error) {
if (error.name === 'SyntaxError') {
return /^(Unexpected end of input|Unexpected token)/.test(error.message)
}
return false
}
exports.start = () => {
const testClient = axios.create({
baseURL: `http://localhost:${config.port}/`,
validateStatus: () => true
})
console.log('')
console.log(`命令格式:${chalkColored.green('[get]/post/put/delete')} 路由 ${chalkColored.cyan('[参数1=值1...]')}`)
console.log(`命令示例:${chalkColored.green('put')} api/card ${chalkColored.cyan('amount=0.2 password=123456')}`)
console.log('')
console.log(`1. auth 请求省略形式:${chalkColored.blue('auth 一卡通号')};使用 ${chalkColored.blue('delete auth')} 退出登录。`)
console.log(` 成功后 token 将保存,后续请求都会自动带上`)
console.log('2. 需要传复杂参数直接用 js 格式书写即可,支持 JSON 兼容的任何类型:')
console.log(` ${chalkColored.green('put')} api/card ${chalkColored.cyan('{ amount: 0.2, password: 123456 }')}`)
let replServer = repl.start({
prompt: '\n> ',
eval: (cmd, context, filename, callback) => {
let parts = /^(?:(get|post|put|delete)\s+)?(\S+)(?:\s+([\s\S]+))?$/im.exec(cmd.trim())
if (!parts) {
return callback(null)
}
let [method, path, params] = parts.slice(1)
let composedParams = {}
if (params) {
if (/^(\S+=\S+)(\s+(\S+=\S+))*$/m.test(params)) {
params.split(/\s+/g).map(param => {
let [key, value] = param.split('=')
composedParams[key] = value
})
} else if (/^auth$/.test(path) && !method) {
oracle.getConnection().then(async (db) => {
const cardnum = params
let name, schoolnum=null
if (cardnum.startsWith('21')) {
// 本科生库
const record = await db.execute(
`SELECT XM, XJH FROM T_BZKS_TMP
WHERE XH=:cardnum`, [cardnum]
)
if (record.rows.length > 0) {
name = record.rows[0][0]
schoolnum = record.rows[0][1]
}
} else if (cardnum.startsWith('10')) {
// 教职工库
const record = await db.execute(
`SELECT XM FROM T_JZG_JBXX_TMP
WHERE ZGH=:cardnum`, [cardnum]
)
if (record.rows.length > 0) {
name = record.rows[0][0]
}
}
if (!name) {
console.log('身份完整性校验失败')
callback(null)
await db.close()
return
}
// 生成 32 字节 token 转为十六进制,及其哈希值
let token = Buffer.from(crypto.randomBytes(20)).toString('hex')
let tokenHash = hash(token)
// 防止数据库被挤爆,也为了安全性,先删除用户已有的 repl token
await db.execute(`DELETE FROM XSC_AUTH WHERE CARDNUM = :cardnum AND PLATFORM = 'repl'`,
{cardnum})
// 将新用户信息插入数据库
let now = moment()
// 向数据库插入记录
const dbResult = await db.execute(
`INSERT INTO XSC_AUTH
(TOKEN_HASH, CARDNUM, REAL_NAME, CREATED_TIME, PLATFORM, LAST_INVOKED_TIME, SCHOOLNUM, FROM_WECHAT)
VALUES (:tokenHash, :cardnum, :name, :createdTime, 'repl', :lastInvokedTime, :schoolnum, :fromWechat )
`,
{
tokenHash,
cardnum,
name,
createdTime:now.toDate(),
lastInvokedTime:now.toDate(),
schoolnum,
fromWechat:0
}
)
if(dbResult.rowsAffected === 1){
console.log(`当前认证身份:${cardnum} - ${name} - ${schoolnum}`)
console.log(`如需调试,在浏览器控制台执行: auth('${token}')`)
testClient.defaults.headers = { 'x-api-token': token }
}
callback(null)
await db.close()
})
return
} else {
try {
composedParams = vm.runInThisContext('(' + params + ')')
} catch (e) {
if (isRecoverableError(e)) {
return callback(new repl.Recoverable(e))
} else {
console.error(e.message)
return callback(null)
}
}
}
}
if (!method) {
method = 'get'
} else {
method = method.toLowerCase()
}
if (Object.keys(composedParams).length && (method === 'get' || method === 'delete')) {
path += '?' + qs.stringify(composedParams)
composedParams = {}
}
testClient[method](path, composedParams).then(res => {
if (/^\/?auth$/.test(path) && res.data.result) {
if (method === 'post') {
console.log(`\n登录成功了!`)
testClient.defaults.headers = { token: res.data.result }
} else if (method === 'delete') {
console.log('\n退出登录了!')
testClient.defaults.headers = {}
}
}
console.log('\n' + prettyjson.render(res.data))
callback(null)
})
}
})
replServer.on('exit', () => {
console.log('退出服务器了!')
process.exit()
})
require('./replHistory')(replServer, './.repl_history')
}