@jayfong/x-server 2.16.4 → 2.17.0
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/lib/_cjs/services/cache.js +24 -8
- package/lib/_cjs/services/captcha.js +27 -15
- package/lib/services/cache.d.ts +14 -6
- package/lib/services/cache.js +24 -8
- package/lib/services/captcha.d.ts +14 -6
- package/lib/services/captcha.js +27 -15
- package/package.json +1 -1
|
@@ -11,7 +11,9 @@ class CacheService {
|
|
|
11
11
|
this.options = options;
|
|
12
12
|
this.serviceName = 'cache';
|
|
13
13
|
this.prefix = void 0;
|
|
14
|
+
this.memoryCache = void 0;
|
|
14
15
|
this.prefix = `${_x.x.appId}:`;
|
|
16
|
+
this.memoryCache = !options.memory ? undefined : new Map();
|
|
15
17
|
}
|
|
16
18
|
toRedisKey(key) {
|
|
17
19
|
return `${this.prefix}${Array.isArray(key) ? key.join('_') : String(key)}`;
|
|
@@ -22,10 +24,11 @@ class CacheService {
|
|
|
22
24
|
*
|
|
23
25
|
* @param key 键
|
|
24
26
|
* @param value 值
|
|
25
|
-
* @param
|
|
27
|
+
* @param ttlOrOptions 缓存时间或选项
|
|
26
28
|
* @returns 返回设置的缓存内容
|
|
27
29
|
*/
|
|
28
|
-
async set(key, value,
|
|
30
|
+
async set(key, value, ttlOrOptions) {
|
|
31
|
+
const ttl = ttlOrOptions == null ? this.options.ttl : typeof ttlOrOptions === 'object' ? ttlOrOptions.ttl : ttlOrOptions;
|
|
29
32
|
const redisTtl = typeof ttl === 'function' ? ttl(value, this.options.ttl) : ttl;
|
|
30
33
|
if (redisTtl) {
|
|
31
34
|
const redisKey = this.toRedisKey(key);
|
|
@@ -33,6 +36,9 @@ class CacheService {
|
|
|
33
36
|
await _x.x.redis.set(redisKey, redisValue,
|
|
34
37
|
// 毫秒
|
|
35
38
|
'PX', (0, _vtils.ms)(redisTtl));
|
|
39
|
+
if (this.options.memory) {
|
|
40
|
+
this.memoryCache.set(redisKey, value);
|
|
41
|
+
}
|
|
36
42
|
}
|
|
37
43
|
return value;
|
|
38
44
|
}
|
|
@@ -53,10 +59,14 @@ class CacheService {
|
|
|
53
59
|
* 获取缓存内容。
|
|
54
60
|
*
|
|
55
61
|
* @param key 键
|
|
62
|
+
* @param options 选项
|
|
56
63
|
* @returns 返回获取到的缓存内容
|
|
57
64
|
*/
|
|
58
65
|
async get(key) {
|
|
59
66
|
const redisKey = this.toRedisKey(key);
|
|
67
|
+
if (this.options.memory && this.memoryCache.has(redisKey)) {
|
|
68
|
+
return this.memoryCache.get(redisKey);
|
|
69
|
+
}
|
|
60
70
|
const gotValue = await _x.x.redis.get(redisKey);
|
|
61
71
|
if (gotValue) {
|
|
62
72
|
try {
|
|
@@ -102,18 +112,18 @@ class CacheService {
|
|
|
102
112
|
*
|
|
103
113
|
* @param key 键
|
|
104
114
|
* @param action 获取缓存内容的操作
|
|
105
|
-
* @param
|
|
115
|
+
* @param ttlOrOptions 缓存时间或选项
|
|
106
116
|
* @returns 返回获取到的内容
|
|
107
117
|
*/
|
|
108
|
-
async remember(key, action,
|
|
118
|
+
async remember(key, action, ttlOrOptions) {
|
|
109
119
|
let value = await this.get(key);
|
|
110
120
|
if (value === null) {
|
|
111
121
|
value = await action();
|
|
112
|
-
await this.set(key, value,
|
|
122
|
+
await this.set(key, value, ttlOrOptions);
|
|
113
123
|
}
|
|
114
124
|
return value;
|
|
115
125
|
}
|
|
116
|
-
async rememberMany(raws, key, action,
|
|
126
|
+
async rememberMany(raws, key, action, ttlOrOptions) {
|
|
117
127
|
const keys = raws.map(key);
|
|
118
128
|
const values = await this.getMany(...keys);
|
|
119
129
|
const shouldUpdateIndexes = [];
|
|
@@ -126,7 +136,7 @@ class CacheService {
|
|
|
126
136
|
const nextValues = await action(shouldUpdateIndexes.map(i => raws[i]));
|
|
127
137
|
await Promise.all(nextValues.map(async (nextValue, index) => {
|
|
128
138
|
values[shouldUpdateIndexes[index]] = nextValue;
|
|
129
|
-
await this.set(keys[shouldUpdateIndexes[index]], nextValue,
|
|
139
|
+
await this.set(keys[shouldUpdateIndexes[index]], nextValue, ttlOrOptions);
|
|
130
140
|
}));
|
|
131
141
|
}
|
|
132
142
|
return values;
|
|
@@ -193,7 +203,13 @@ class CacheService {
|
|
|
193
203
|
if (!keys.length) {
|
|
194
204
|
return 0;
|
|
195
205
|
}
|
|
196
|
-
|
|
206
|
+
const redisKeys = keys.map(key => this.toRedisKey(key));
|
|
207
|
+
if (this.options.memory) {
|
|
208
|
+
redisKeys.forEach(redisKey => {
|
|
209
|
+
this.memoryCache.delete(redisKey);
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
return _x.x.redis.del(...redisKeys);
|
|
197
213
|
}
|
|
198
214
|
|
|
199
215
|
/**
|
|
@@ -3,36 +3,51 @@
|
|
|
3
3
|
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
|
|
4
4
|
exports.__esModule = true;
|
|
5
5
|
exports.CaptchaService = void 0;
|
|
6
|
-
var _svgCaptcha = _interopRequireDefault(require("svg-captcha"));
|
|
7
6
|
var _miniSvgDataUri = _interopRequireDefault(require("mini-svg-data-uri"));
|
|
7
|
+
var _svgCaptcha = _interopRequireDefault(require("svg-captcha"));
|
|
8
|
+
var _vtils = require("vtils");
|
|
8
9
|
var _x = require("../x");
|
|
9
10
|
class CaptchaService {
|
|
10
|
-
constructor(
|
|
11
|
-
this.options = options;
|
|
11
|
+
constructor() {
|
|
12
12
|
this.serviceName = 'captcha';
|
|
13
|
+
this.charsetMap = {
|
|
14
|
+
'09': '0123456789'.split(''),
|
|
15
|
+
'19': '123456789'.split(''),
|
|
16
|
+
'az': 'abcdefghijklmnopqrstuvwxyz'.split(''),
|
|
17
|
+
'AZ': 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''),
|
|
18
|
+
'aZ': 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''),
|
|
19
|
+
'0z': '0123456789abcdefghijklmnopqrstuvwxyz'.split(''),
|
|
20
|
+
'0Z': '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''),
|
|
21
|
+
'1z': '123456789abcdefghijklmnopqrstuvwxyz'.split(''),
|
|
22
|
+
'1Z': '123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('')
|
|
23
|
+
};
|
|
13
24
|
}
|
|
14
|
-
async generate(
|
|
15
|
-
const
|
|
25
|
+
async generate(payload) {
|
|
26
|
+
const chars = this.charsetMap[payload.charset];
|
|
27
|
+
let code = '';
|
|
28
|
+
for (let i = 0; i < payload.size; i++) {
|
|
29
|
+
code += (0, _vtils.sample)(chars);
|
|
30
|
+
}
|
|
16
31
|
const token = await _x.x.cache.save({
|
|
17
|
-
code,
|
|
18
|
-
scene
|
|
19
|
-
},
|
|
32
|
+
code: code,
|
|
33
|
+
scene: payload.scene
|
|
34
|
+
}, payload.ttl);
|
|
20
35
|
return {
|
|
21
36
|
token: token,
|
|
22
37
|
code: code
|
|
23
38
|
};
|
|
24
39
|
}
|
|
25
|
-
async generateDataUrl(
|
|
40
|
+
async generateDataUrl(payload) {
|
|
26
41
|
const {
|
|
27
42
|
text: code,
|
|
28
43
|
data: svg
|
|
29
44
|
} = _svgCaptcha.default.create({
|
|
30
|
-
size:
|
|
45
|
+
size: payload.size
|
|
31
46
|
});
|
|
32
47
|
const token = await _x.x.cache.save({
|
|
33
48
|
code,
|
|
34
|
-
scene
|
|
35
|
-
},
|
|
49
|
+
scene: payload.scene
|
|
50
|
+
}, payload.ttl);
|
|
36
51
|
const dataUrl = (0, _miniSvgDataUri.default)(svg);
|
|
37
52
|
return {
|
|
38
53
|
token: token,
|
|
@@ -41,9 +56,6 @@ class CaptchaService {
|
|
|
41
56
|
};
|
|
42
57
|
}
|
|
43
58
|
async verify(options) {
|
|
44
|
-
if (options.code.length !== this.options.size) {
|
|
45
|
-
return false;
|
|
46
|
-
}
|
|
47
59
|
const expected = await _x.x.cache.get(options.token);
|
|
48
60
|
if (expected == null) {
|
|
49
61
|
return false;
|
package/lib/services/cache.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { MsValue } from 'vtils';
|
|
1
2
|
import { AsyncOrSync, IsEmptyArray } from 'vtils/types';
|
|
2
3
|
import { BaseService } from './base';
|
|
3
|
-
import { MsValue } from 'vtils';
|
|
4
4
|
export interface CacheServiceOptions {
|
|
5
5
|
/** 默认过期时间 */
|
|
6
6
|
ttl: MsValue;
|
|
7
|
+
/** 启用内存缓存,仅 get, set, remove, remember 支持 */
|
|
8
|
+
memory?: boolean;
|
|
7
9
|
}
|
|
8
10
|
type Data = {
|
|
9
11
|
[K in string]: (...args: any[]) => any;
|
|
@@ -16,10 +18,15 @@ type KeyPathForNumberValue<T extends Data> = {
|
|
|
16
18
|
[K in keyof T]: T[K] extends (...args: infer X) => number ? IsEmptyArray<X> extends true ? K : [K, ...X] : never;
|
|
17
19
|
}[keyof T];
|
|
18
20
|
type Value<T extends Data, P extends KeyPath<T>> = ReturnType<T[P extends any[] ? P[0] : P]>;
|
|
21
|
+
type CacheSetTTL<V> = MsValue | ((data: V, defaultTTL: MsValue) => MsValue);
|
|
22
|
+
type CacheSetOptions<V> = CacheSetTTL<V> | {
|
|
23
|
+
ttl?: CacheSetTTL<V>;
|
|
24
|
+
};
|
|
19
25
|
export declare class CacheService<TData extends Data = Data, TKey extends Key<TData> = any, TKeyPath extends KeyPath<TData> = any, TKeyPathForNumberValue extends KeyPathForNumberValue<TData> = any> implements BaseService {
|
|
20
26
|
options: CacheServiceOptions;
|
|
21
27
|
serviceName: string;
|
|
22
28
|
private prefix;
|
|
29
|
+
private memoryCache;
|
|
23
30
|
constructor(options: CacheServiceOptions);
|
|
24
31
|
private toRedisKey;
|
|
25
32
|
/**
|
|
@@ -27,10 +34,10 @@ export declare class CacheService<TData extends Data = Data, TKey extends Key<TD
|
|
|
27
34
|
*
|
|
28
35
|
* @param key 键
|
|
29
36
|
* @param value 值
|
|
30
|
-
* @param
|
|
37
|
+
* @param ttlOrOptions 缓存时间或选项
|
|
31
38
|
* @returns 返回设置的缓存内容
|
|
32
39
|
*/
|
|
33
|
-
set<K extends TKeyPath, V extends Value<TData, K>>(key: K, value: V,
|
|
40
|
+
set<K extends TKeyPath, V extends Value<TData, K>>(key: K, value: V, ttlOrOptions?: CacheSetOptions<V>): Promise<V>;
|
|
34
41
|
/**
|
|
35
42
|
* 存储值然后返回其对应的键,该键 URL 友好。
|
|
36
43
|
*
|
|
@@ -42,6 +49,7 @@ export declare class CacheService<TData extends Data = Data, TKey extends Key<TD
|
|
|
42
49
|
* 获取缓存内容。
|
|
43
50
|
*
|
|
44
51
|
* @param key 键
|
|
52
|
+
* @param options 选项
|
|
45
53
|
* @returns 返回获取到的缓存内容
|
|
46
54
|
*/
|
|
47
55
|
get<K extends TKeyPath, V extends Value<TData, K>>(key: K): Promise<V | null>;
|
|
@@ -64,11 +72,11 @@ export declare class CacheService<TData extends Data = Data, TKey extends Key<TD
|
|
|
64
72
|
*
|
|
65
73
|
* @param key 键
|
|
66
74
|
* @param action 获取缓存内容的操作
|
|
67
|
-
* @param
|
|
75
|
+
* @param ttlOrOptions 缓存时间或选项
|
|
68
76
|
* @returns 返回获取到的内容
|
|
69
77
|
*/
|
|
70
|
-
remember<K extends TKeyPath, V extends Value<TData, K>>(key: K, action: () => V | Promise<V>,
|
|
71
|
-
rememberMany<T, K extends TKeyPath, V extends Value<TData, K>>(raws: T[], key: (raw: T) => K, action: (raws: T[]) => V[] | Promise<V[]>,
|
|
78
|
+
remember<K extends TKeyPath, V extends Value<TData, K>>(key: K, action: () => V | Promise<V>, ttlOrOptions?: CacheSetOptions<V>): Promise<V>;
|
|
79
|
+
rememberMany<T, K extends TKeyPath, V extends Value<TData, K>>(raws: T[], key: (raw: T) => K, action: (raws: T[]) => V[] | Promise<V[]>, ttlOrOptions?: CacheSetOptions<V>): Promise<V[]>;
|
|
72
80
|
/**
|
|
73
81
|
* 自增。
|
|
74
82
|
*
|
package/lib/services/cache.js
CHANGED
|
@@ -6,7 +6,9 @@ export class CacheService {
|
|
|
6
6
|
this.options = options;
|
|
7
7
|
this.serviceName = 'cache';
|
|
8
8
|
this.prefix = void 0;
|
|
9
|
+
this.memoryCache = void 0;
|
|
9
10
|
this.prefix = `${x.appId}:`;
|
|
11
|
+
this.memoryCache = !options.memory ? undefined : new Map();
|
|
10
12
|
}
|
|
11
13
|
toRedisKey(key) {
|
|
12
14
|
return `${this.prefix}${Array.isArray(key) ? key.join('_') : String(key)}`;
|
|
@@ -17,10 +19,11 @@ export class CacheService {
|
|
|
17
19
|
*
|
|
18
20
|
* @param key 键
|
|
19
21
|
* @param value 值
|
|
20
|
-
* @param
|
|
22
|
+
* @param ttlOrOptions 缓存时间或选项
|
|
21
23
|
* @returns 返回设置的缓存内容
|
|
22
24
|
*/
|
|
23
|
-
async set(key, value,
|
|
25
|
+
async set(key, value, ttlOrOptions) {
|
|
26
|
+
const ttl = ttlOrOptions == null ? this.options.ttl : typeof ttlOrOptions === 'object' ? ttlOrOptions.ttl : ttlOrOptions;
|
|
24
27
|
const redisTtl = typeof ttl === 'function' ? ttl(value, this.options.ttl) : ttl;
|
|
25
28
|
if (redisTtl) {
|
|
26
29
|
const redisKey = this.toRedisKey(key);
|
|
@@ -28,6 +31,9 @@ export class CacheService {
|
|
|
28
31
|
await x.redis.set(redisKey, redisValue,
|
|
29
32
|
// 毫秒
|
|
30
33
|
'PX', ms(redisTtl));
|
|
34
|
+
if (this.options.memory) {
|
|
35
|
+
this.memoryCache.set(redisKey, value);
|
|
36
|
+
}
|
|
31
37
|
}
|
|
32
38
|
return value;
|
|
33
39
|
}
|
|
@@ -48,10 +54,14 @@ export class CacheService {
|
|
|
48
54
|
* 获取缓存内容。
|
|
49
55
|
*
|
|
50
56
|
* @param key 键
|
|
57
|
+
* @param options 选项
|
|
51
58
|
* @returns 返回获取到的缓存内容
|
|
52
59
|
*/
|
|
53
60
|
async get(key) {
|
|
54
61
|
const redisKey = this.toRedisKey(key);
|
|
62
|
+
if (this.options.memory && this.memoryCache.has(redisKey)) {
|
|
63
|
+
return this.memoryCache.get(redisKey);
|
|
64
|
+
}
|
|
55
65
|
const gotValue = await x.redis.get(redisKey);
|
|
56
66
|
if (gotValue) {
|
|
57
67
|
try {
|
|
@@ -97,18 +107,18 @@ export class CacheService {
|
|
|
97
107
|
*
|
|
98
108
|
* @param key 键
|
|
99
109
|
* @param action 获取缓存内容的操作
|
|
100
|
-
* @param
|
|
110
|
+
* @param ttlOrOptions 缓存时间或选项
|
|
101
111
|
* @returns 返回获取到的内容
|
|
102
112
|
*/
|
|
103
|
-
async remember(key, action,
|
|
113
|
+
async remember(key, action, ttlOrOptions) {
|
|
104
114
|
let value = await this.get(key);
|
|
105
115
|
if (value === null) {
|
|
106
116
|
value = await action();
|
|
107
|
-
await this.set(key, value,
|
|
117
|
+
await this.set(key, value, ttlOrOptions);
|
|
108
118
|
}
|
|
109
119
|
return value;
|
|
110
120
|
}
|
|
111
|
-
async rememberMany(raws, key, action,
|
|
121
|
+
async rememberMany(raws, key, action, ttlOrOptions) {
|
|
112
122
|
const keys = raws.map(key);
|
|
113
123
|
const values = await this.getMany(...keys);
|
|
114
124
|
const shouldUpdateIndexes = [];
|
|
@@ -121,7 +131,7 @@ export class CacheService {
|
|
|
121
131
|
const nextValues = await action(shouldUpdateIndexes.map(i => raws[i]));
|
|
122
132
|
await Promise.all(nextValues.map(async (nextValue, index) => {
|
|
123
133
|
values[shouldUpdateIndexes[index]] = nextValue;
|
|
124
|
-
await this.set(keys[shouldUpdateIndexes[index]], nextValue,
|
|
134
|
+
await this.set(keys[shouldUpdateIndexes[index]], nextValue, ttlOrOptions);
|
|
125
135
|
}));
|
|
126
136
|
}
|
|
127
137
|
return values;
|
|
@@ -188,7 +198,13 @@ export class CacheService {
|
|
|
188
198
|
if (!keys.length) {
|
|
189
199
|
return 0;
|
|
190
200
|
}
|
|
191
|
-
|
|
201
|
+
const redisKeys = keys.map(key => this.toRedisKey(key));
|
|
202
|
+
if (this.options.memory) {
|
|
203
|
+
redisKeys.forEach(redisKey => {
|
|
204
|
+
this.memoryCache.delete(redisKey);
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
return x.redis.del(...redisKeys);
|
|
192
208
|
}
|
|
193
209
|
|
|
194
210
|
/**
|
|
@@ -1,6 +1,11 @@
|
|
|
1
|
+
import { type MsValue } from 'vtils';
|
|
1
2
|
import { BaseService } from './base';
|
|
2
|
-
|
|
3
|
-
export interface
|
|
3
|
+
export type CaptchaServiceGenerateCharset = '09' | '19' | 'az' | 'AZ' | 'aZ' | '0z' | '0Z' | '1z' | '1Z';
|
|
4
|
+
export interface CaptchaServiceGeneratePayload {
|
|
5
|
+
/**
|
|
6
|
+
* 场景值
|
|
7
|
+
*/
|
|
8
|
+
scene: string;
|
|
4
9
|
/**
|
|
5
10
|
* 验证码长度
|
|
6
11
|
*/
|
|
@@ -9,6 +14,10 @@ export interface CaptchaServiceOptions {
|
|
|
9
14
|
* 验证码存活时长
|
|
10
15
|
*/
|
|
11
16
|
ttl: MsValue;
|
|
17
|
+
/**
|
|
18
|
+
* 字符集
|
|
19
|
+
*/
|
|
20
|
+
charset: CaptchaServiceGenerateCharset;
|
|
12
21
|
}
|
|
13
22
|
export interface CaptchaServiceGenerateResult {
|
|
14
23
|
token: string;
|
|
@@ -30,11 +39,10 @@ export interface CaptchaServiceVerifyOptions {
|
|
|
30
39
|
scene: string;
|
|
31
40
|
}
|
|
32
41
|
export declare class CaptchaService implements BaseService {
|
|
33
|
-
private options;
|
|
34
42
|
serviceName: string;
|
|
35
|
-
|
|
36
|
-
generate(
|
|
37
|
-
generateDataUrl(
|
|
43
|
+
private charsetMap;
|
|
44
|
+
generate(payload: CaptchaServiceGeneratePayload): Promise<CaptchaServiceGenerateResult>;
|
|
45
|
+
generateDataUrl(payload: CaptchaServiceGeneratePayload): Promise<CaptchaServiceGenerateDataUrlResult>;
|
|
38
46
|
verify(options: CaptchaServiceVerifyOptions): Promise<boolean>;
|
|
39
47
|
}
|
|
40
48
|
declare module '../x' {
|
package/lib/services/captcha.js
CHANGED
|
@@ -1,33 +1,48 @@
|
|
|
1
|
-
import svgCaptcha from 'svg-captcha';
|
|
2
1
|
import svgToDataUrl from 'mini-svg-data-uri';
|
|
2
|
+
import svgCaptcha from 'svg-captcha';
|
|
3
|
+
import { sample } from 'vtils';
|
|
3
4
|
import { x } from "../x";
|
|
4
5
|
export class CaptchaService {
|
|
5
|
-
constructor(
|
|
6
|
-
this.options = options;
|
|
6
|
+
constructor() {
|
|
7
7
|
this.serviceName = 'captcha';
|
|
8
|
+
this.charsetMap = {
|
|
9
|
+
'09': '0123456789'.split(''),
|
|
10
|
+
'19': '123456789'.split(''),
|
|
11
|
+
'az': 'abcdefghijklmnopqrstuvwxyz'.split(''),
|
|
12
|
+
'AZ': 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''),
|
|
13
|
+
'aZ': 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''),
|
|
14
|
+
'0z': '0123456789abcdefghijklmnopqrstuvwxyz'.split(''),
|
|
15
|
+
'0Z': '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''),
|
|
16
|
+
'1z': '123456789abcdefghijklmnopqrstuvwxyz'.split(''),
|
|
17
|
+
'1Z': '123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('')
|
|
18
|
+
};
|
|
8
19
|
}
|
|
9
|
-
async generate(
|
|
10
|
-
const
|
|
20
|
+
async generate(payload) {
|
|
21
|
+
const chars = this.charsetMap[payload.charset];
|
|
22
|
+
let code = '';
|
|
23
|
+
for (let i = 0; i < payload.size; i++) {
|
|
24
|
+
code += sample(chars);
|
|
25
|
+
}
|
|
11
26
|
const token = await x.cache.save({
|
|
12
|
-
code,
|
|
13
|
-
scene
|
|
14
|
-
},
|
|
27
|
+
code: code,
|
|
28
|
+
scene: payload.scene
|
|
29
|
+
}, payload.ttl);
|
|
15
30
|
return {
|
|
16
31
|
token: token,
|
|
17
32
|
code: code
|
|
18
33
|
};
|
|
19
34
|
}
|
|
20
|
-
async generateDataUrl(
|
|
35
|
+
async generateDataUrl(payload) {
|
|
21
36
|
const {
|
|
22
37
|
text: code,
|
|
23
38
|
data: svg
|
|
24
39
|
} = svgCaptcha.create({
|
|
25
|
-
size:
|
|
40
|
+
size: payload.size
|
|
26
41
|
});
|
|
27
42
|
const token = await x.cache.save({
|
|
28
43
|
code,
|
|
29
|
-
scene
|
|
30
|
-
},
|
|
44
|
+
scene: payload.scene
|
|
45
|
+
}, payload.ttl);
|
|
31
46
|
const dataUrl = svgToDataUrl(svg);
|
|
32
47
|
return {
|
|
33
48
|
token: token,
|
|
@@ -36,9 +51,6 @@ export class CaptchaService {
|
|
|
36
51
|
};
|
|
37
52
|
}
|
|
38
53
|
async verify(options) {
|
|
39
|
-
if (options.code.length !== this.options.size) {
|
|
40
|
-
return false;
|
|
41
|
-
}
|
|
42
54
|
const expected = await x.cache.get(options.token);
|
|
43
55
|
if (expected == null) {
|
|
44
56
|
return false;
|