topbit 3.1.5 → 3.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.cn.md CHANGED
@@ -1411,7 +1411,7 @@ https_server.listen(2026)
1411
1411
 
1412
1412
  ## 请求限流
1413
1413
 
1414
- 框架层面提供的限流是基于IP地址的计算和过滤,避免同一个IP地址密集的发送请求。若使用HTTP/2协议,则需要配合使用topbit-toolkit扩展的http2limit模块。
1414
+ 框架层面提供的限流是基于IP地址的计算和过滤,避免同一个IP地址密集的发送请求。若使用HTTP/2协议,则需要配合使用扩展http2limit模块。
1415
1415
 
1416
1416
  ```javascript
1417
1417
  'use strict';
@@ -2047,8 +2047,21 @@ app.use(pck, {method: 'GET'})
2047
2047
  let pmbody = new ParamCheck({
2048
2048
  key: 'body',
2049
2049
  rule: {
2050
- username: { must: true },
2051
- passwd: { must: true }
2050
+ username: {
2051
+ must: true,
2052
+ //min length
2053
+ min: 5,
2054
+ //max length
2055
+ max: 30
2056
+ },
2057
+ passwd: {
2058
+ must: true,
2059
+ min: 7,
2060
+ max: 20
2061
+ },
2062
+ mobile: {
2063
+ regex: /^(12|13|15|16|17|18|19)[0-9]{9}$/
2064
+ }
2052
2065
  }
2053
2066
  })
2054
2067
 
@@ -2065,7 +2078,7 @@ JWT 协议的 Token 验证与签发。推荐使用 `Topbit.Token` 替代。
2065
2078
  const Topbit = require('topbit')
2066
2079
  const {JWT} = Topbit.extensions
2067
2080
 
2068
- let j = new JWT({
2081
+ let j = new KWT({
2069
2082
  timeout: 7200000, // 超时时间
2070
2083
  })
2071
2084
  j.alg = 'hs512' // 设置算法
package/README.md CHANGED
@@ -1999,8 +1999,21 @@ app.use(pck, {method: 'GET'})
1999
1999
  let pmbody = new ParamCheck({
2000
2000
  key: 'body',
2001
2001
  rule: {
2002
- username: { must: true },
2003
- passwd: { must: true }
2002
+ username: {
2003
+ must: true,
2004
+ //min length
2005
+ min: 5,
2006
+ //max length
2007
+ max: 30
2008
+ },
2009
+ passwd: {
2010
+ must: true,
2011
+ min: 7,
2012
+ max: 20
2013
+ },
2014
+ mobile: {
2015
+ regex: /^(12|13|15|16|17|18|19)[0-9]{9}$/
2016
+ }
2004
2017
  }
2005
2018
  })
2006
2019
 
package/demo/rule.js CHANGED
@@ -93,6 +93,23 @@ let pmbody = new ParamCheck({
93
93
  },
94
94
  passwd: {
95
95
  must: true
96
+ },
97
+
98
+ mobile: {
99
+ errorMessage: '手机号不符合要求',
100
+ regex: /^(12|13|14|15|16|17|18|19)[0-9]{9}$/,
101
+ },
102
+
103
+ detail: {
104
+ errorMessage: 'detail长度0~10',
105
+ min: 0,
106
+ max: 10
107
+ },
108
+
109
+ age: {
110
+ to: 'int',
111
+ min: 15,
112
+ max: 95
96
113
  }
97
114
  }
98
115
  })
@@ -52,9 +52,8 @@ module.exports = token
52
52
  async post(c) {
53
53
  // After successful login
54
54
  const userinfo = { uid: 1, name: 'Alice', role: 'admin' }
55
- const t = token.make(userinfo)
56
- c.setHeader('authorization', t)
57
- c.to({ok: true})
55
+ const t = token.makeToken(userinfo)
56
+ c.to({ok: true, token: t})
58
57
  }
59
58
 
60
59
  // All protected routes automatically use token.mid()
@@ -59,9 +59,8 @@ class User {
59
59
  role : 'admin',
60
60
  // expires 可单独设置更长时间
61
61
  }
62
- let t = token.make(userinfo) // 签发 Token
63
- c.setHeader('authorization', t)
64
- c.to({ok: true, msg: 'login success'})
62
+ let t = token.makeToken(userinfo) // 签发 Token
63
+ c.to({ok: true, msg: 'login success', token: t})
65
64
  }
66
65
  }
67
66
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "topbit",
3
- "version": "3.1.5",
3
+ "version": "3.1.7",
4
4
  "description": "A Server-side web framework support http/1.1 and http/2",
5
5
  "main": "src/topbit.js",
6
6
  "directories": {
@@ -30,7 +30,7 @@ class ParamCheck {
30
30
 
31
31
  case 'rule':
32
32
  if (typeof options[k] === 'object') {
33
- this.rule = options[k]
33
+ this.rule = {...options[k]}
34
34
  }
35
35
  break
36
36
 
@@ -51,17 +51,20 @@ class ParamCheck {
51
51
  this.deleteDeny = !!options[k]
52
52
  break
53
53
 
54
- default:
54
+ default:
55
55
  this[k] = options[k]
56
56
  }
57
57
  }
58
58
 
59
+ this.ruleKeys = Object.keys(this.rule)
60
+
59
61
  let data_type = ''
60
- for (let k in this.rule) {
62
+ for (let k of this.ruleKeys) {
61
63
  data_type = typeof this.rule[k]
62
64
 
63
65
  if (data_type === 'string' || data_type === 'number') {
64
66
  this.rule[k] = {
67
+ __is_regex__: false,
65
68
  __is_value__: true,
66
69
  __value__: this.rule[k],
67
70
  __type__: data_type === 'string' ? TYPE_STRING : TYPE_NUMBER
@@ -70,6 +73,20 @@ class ParamCheck {
70
73
  continue
71
74
  }
72
75
 
76
+ if (this.rule[k] instanceof RegExp) {
77
+ this.rule[k] = {
78
+ __is_regex__: true,
79
+ __is_value__: false,
80
+ regex: this.rule[k]
81
+ }
82
+
83
+ continue
84
+ }
85
+
86
+ if (this.rule[k].regex && this.rule[k].regex instanceof RegExp) {
87
+ this.rule[k].__is_regex__ = true
88
+ }
89
+
73
90
  this.rule[k].__is_value__ = false
74
91
 
75
92
  if (this.rule[k].callback && typeof this.rule[k].callback === 'function') {
@@ -82,11 +99,11 @@ class ParamCheck {
82
99
  }
83
100
 
84
101
  /**
85
- *
102
+ *
86
103
  * @param {object} obj c.param or c.query
87
104
  * @param {*} k key name
88
105
  * @param {*} rule filter rule
89
- *
106
+ *
90
107
  * rule描述了如何进行数据的过滤,如果rule是字符串或数字则要求严格相等。
91
108
  * 否则rule应该是一个object,可以包括的属性如下:
92
109
  * - callback 用于过滤的回调函数,在验证时,会传递数据,除此之外没有其他参数。
@@ -108,7 +125,7 @@ class ParamCheck {
108
125
  ost.ok = false
109
126
  return false
110
127
  }
111
-
128
+
112
129
  if (rule.default !== undefined) {
113
130
  obj[k] = rule.default
114
131
  return true
@@ -117,49 +134,80 @@ class ParamCheck {
117
134
  } else {
118
135
  //数据初始必然是字符串,转换只能是整数或浮点数或boolean。
119
136
  if (rule.to) {
120
- if (isNaN(obj[k])) {
137
+ let is_number = typeof obj[k] === 'number'
138
+
139
+ if (is_number) {
140
+ if (rule.to === 'int') {
141
+ obj[k] = Math.floor(obj[k])
142
+ } else if (rule.to === 'boolean' || rule.to === 'bool') {
143
+ obj[k] = !!obj[k]
144
+ }
145
+ } else {
146
+ switch(rule.to) {
147
+ case 'int':
148
+ obj[k] = parseInt(obj[k])
149
+ if (isNaN(obj[k])) {
150
+ if (rule.default !== undefined) {
151
+ obj[k] = rule.default
152
+ return true
153
+ }
154
+ ost.ok = false
155
+ return false
156
+ }
157
+ break
158
+
159
+ case 'float':
160
+ obj[k] = parseFloat(obj[k])
161
+ if (isNaN(obj[k])) {
162
+ if (rule.default !== undefined) {
163
+ obj[k] = rule.default
164
+ return true
165
+ }
166
+ ost.ok = false
167
+ return false
168
+ }
169
+ break
170
+
171
+ case 'boolean':
172
+ case 'bool':
173
+ obj[k] = (obj[k] === 'true' || obj[k] === true || obj[k] == 1) ? true : false
174
+ break
175
+ }
176
+ }
177
+
178
+ if (rule.min !== undefined && obj[k] < rule.min) {
121
179
  ost.ok = false
122
180
  return false
123
181
  }
124
182
 
125
- switch(rule.to) {
126
- case 'int':
127
- obj[k] = parseInt(obj[k])
128
- if (isNaN(obj[k])) {
129
- if (rule.default !== undefined) {
130
- obj[k] = rule.default
131
- return true
132
- }
133
- ost.ok = false
134
- return false
135
- }
136
- break
137
-
138
- case 'float':
139
- obj[k] = parseFloat(obj[k])
140
- if (isNaN(obj[k])) {
141
- if (rule.default !== undefined) {
142
- obj[k] = rule.default
143
- return true
144
- }
145
- ost.ok = false
146
- return false
147
- }
148
- break
149
-
150
- case 'boolean':
151
- case 'bool':
152
- obj[k] = obj[k] === 'true' ? true : false
153
- break
183
+ if (rule.max !== undefined && obj[k] > rule.max) {
184
+ ost.ok = false
185
+ return false
186
+ }
187
+ } else if (typeof obj[k] === 'string') {
188
+ //data is string min and max mean's length
189
+ if (rule.min !== undefined && obj[k].length < rule.min) {
190
+ ost.ok = false
191
+ return false
154
192
  }
155
- }
156
193
 
157
- if (rule.min !== undefined && obj[k] < rule.min) {
158
- ost.ok = false
159
- return false
194
+ if (rule.max !== undefined && obj[k].length > rule.max) {
195
+ ost.ok = false
196
+ return false
197
+ }
198
+ } else if (typeof obj[k] === 'number') {
199
+ if (rule.min !== undefined && obj[k] < rule.min) {
200
+ ost.ok = false
201
+ return false
202
+ }
203
+
204
+ if (rule.max !== undefined && obj[k] > rule.max) {
205
+ ost.ok = false
206
+ return false
207
+ }
160
208
  }
161
209
 
162
- if (rule.max !== undefined && obj[k] > rule.max) {
210
+ if (rule.__is_regex__ && !rule.regex.test(obj[k])) {
163
211
  ost.ok = false
164
212
  return false
165
213
  }
@@ -170,10 +218,11 @@ class ParamCheck {
170
218
  if (rule.callback(obj, k, method) !== false) {
171
219
  return true
172
220
  }
221
+
173
222
  ost.ok = false
174
223
  return false
175
224
  }
176
-
225
+
177
226
  } else if (rule.__type__ === TYPE_STRING) {
178
227
  if (obj[k] === undefined || obj[k] !== rule.__value__) {
179
228
  ost.ok = false
@@ -194,7 +243,7 @@ class ParamCheck {
194
243
  let ost = {ok: true, key: ''}
195
244
 
196
245
  if (this.key !== 'body' || (c.body !== c.rawBody && typeof c.body === 'object')) {
197
- for (let k in this.rule) {
246
+ for (let k of this.ruleKeys) {
198
247
  if (!this.checkData(d, k, this.rule[k], c.method, ost)) {
199
248
  return ost
200
249
  }
@@ -248,7 +297,7 @@ class ParamCheck {
248
297
 
249
298
  await next(c)
250
299
  }
251
-
300
+
252
301
  }
253
302
 
254
303
  return async (c, next) => {
@@ -426,7 +426,7 @@ class TopbitToken {
426
426
  return c.status(self.failedCode).to(uinfo.errcode)
427
427
  }
428
428
 
429
- c.user = uinfo
429
+ c.user = uinfo.data
430
430
 
431
431
  if (uinfo.data.expires + uinfo.data.timestamp - uinfo.now < self.refresh) {
432
432
  let new_token = self.makeToken(uinfo.data, uinfo.data.__tokenId__)