vona-module-captcha-simple 5.1.1
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/LICENSE +21 -0
- package/assets/fonts/Comismsh.ttf +0 -0
- package/assets/fonts/LICENSE.md +2 -0
- package/dist/.metadata/index.d.ts +76 -0
- package/dist/.metadata/index.d.ts.map +1 -0
- package/dist/.metadata/this.d.ts +3 -0
- package/dist/.metadata/this.d.ts.map +1 -0
- package/dist/bean/captchaProvider.imageText.d.ts +18 -0
- package/dist/bean/captchaProvider.imageText.d.ts.map +1 -0
- package/dist/bean/captchaScene.simple.d.ts +4 -0
- package/dist/bean/captchaScene.simple.d.ts.map +1 -0
- package/dist/bean/meta.asset.d.ts +7 -0
- package/dist/bean/meta.asset.d.ts.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +84 -0
- package/dist/index.js.map +1 -0
- package/package.json +43 -0
- package/src/.metadata/index.ts +111 -0
- package/src/.metadata/this.ts +2 -0
- package/src/bean/captchaProvider.imageText.ts +74 -0
- package/src/bean/captchaScene.simple.ts +12 -0
- package/src/bean/meta.asset.ts +9 -0
- package/src/index.ts +1 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2016-present Vona
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
Binary file
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/** captchaProvider: begin */
|
|
2
|
+
export * from '../bean/captchaProvider.imageText.ts';
|
|
3
|
+
import type { ICaptchaProviderOptionsImageText } from '../bean/captchaProvider.imageText.ts';
|
|
4
|
+
import 'vona-module-a-captcha';
|
|
5
|
+
declare module 'vona-module-a-captcha' {
|
|
6
|
+
interface ICaptchaProviderRecord {
|
|
7
|
+
'captcha-simple:imageText': ICaptchaProviderOptionsImageText;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
declare module 'vona-module-captcha-simple' {
|
|
11
|
+
interface CaptchaProviderImageText {
|
|
12
|
+
}
|
|
13
|
+
interface CaptchaProviderImageText {
|
|
14
|
+
get $beanFullName(): 'captcha-simple.captchaProvider.imageText';
|
|
15
|
+
get $onionName(): 'captcha-simple:imageText';
|
|
16
|
+
get $onionOptions(): ICaptchaProviderOptionsImageText;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/** captchaProvider: end */
|
|
20
|
+
/** captchaScene: begin */
|
|
21
|
+
export * from '../bean/captchaScene.simple.ts';
|
|
22
|
+
import { type IDecoratorCaptchaSceneOptions } from 'vona-module-a-captcha';
|
|
23
|
+
declare module 'vona-module-a-captcha' {
|
|
24
|
+
interface ICaptchaSceneRecord {
|
|
25
|
+
'captcha-simple:simple': IDecoratorCaptchaSceneOptions;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
declare module 'vona-module-captcha-simple' {
|
|
29
|
+
interface CaptchaSceneSimple {
|
|
30
|
+
}
|
|
31
|
+
interface CaptchaSceneSimple {
|
|
32
|
+
get $beanFullName(): 'captcha-simple.captchaScene.simple';
|
|
33
|
+
get $onionName(): 'captcha-simple:simple';
|
|
34
|
+
get $onionOptions(): IDecoratorCaptchaSceneOptions;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/** captchaScene: end */
|
|
38
|
+
/** meta: begin */
|
|
39
|
+
export * from '../bean/meta.asset.ts';
|
|
40
|
+
import 'vona-module-a-meta';
|
|
41
|
+
declare module 'vona-module-a-meta' {
|
|
42
|
+
interface IMetaRecord {
|
|
43
|
+
'captcha-simple:asset': never;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
declare module 'vona-module-captcha-simple' {
|
|
47
|
+
interface MetaAsset {
|
|
48
|
+
}
|
|
49
|
+
interface MetaAsset {
|
|
50
|
+
get $beanFullName(): 'captcha-simple.meta.asset';
|
|
51
|
+
get $onionName(): 'captcha-simple:asset';
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/** meta: end */
|
|
55
|
+
/** meta asset: begin */
|
|
56
|
+
import type { MetaAsset } from '../bean/meta.asset.ts';
|
|
57
|
+
/** meta asset: end */
|
|
58
|
+
/** scope: begin */
|
|
59
|
+
import { BeanScopeBase, type BeanScopeUtil } from 'vona';
|
|
60
|
+
export declare class ScopeModuleCaptchaSimple extends BeanScopeBase {
|
|
61
|
+
}
|
|
62
|
+
export interface ScopeModuleCaptchaSimple {
|
|
63
|
+
util: BeanScopeUtil;
|
|
64
|
+
asset: MetaAsset;
|
|
65
|
+
}
|
|
66
|
+
import 'vona';
|
|
67
|
+
declare module 'vona' {
|
|
68
|
+
interface IBeanScopeRecord {
|
|
69
|
+
'captcha-simple': ScopeModuleCaptchaSimple;
|
|
70
|
+
}
|
|
71
|
+
interface IBeanScopeContainer {
|
|
72
|
+
captchaSimple: ScopeModuleCaptchaSimple;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/** scope: end */
|
|
76
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/.metadata/index.ts"],"names":[],"mappings":"AACA,6BAA6B;AAC7B,cAAc,sCAAsC,CAAC;AACrD,OAAO,KAAK,EAAE,gCAAgC,EAAE,MAAM,sCAAsC,CAAC;AAC7F,OAAO,uBAAuB,CAAC;AAC/B,OAAO,QAAQ,uBAAuB,CAAC;IAEnC,UAAiB,sBAAsB;QACrC,0BAA0B,EAAE,gCAAgC,CAAC;KAC9D;CAGJ;AACD,OAAO,QAAQ,4BAA4B,CAAC;IAEpC,UAAiB,wBAAwB;KAGxC;IAEC,UAAiB,wBAAwB;QACvC,IAAI,aAAa,IAAI,0CAA0C,CAAC;QAChE,IAAI,UAAU,IAAI,0BAA0B,CAAC;QAC7C,IAAI,aAAa,IAAI,gCAAgC,CAAC;KACvD;CACV;AACD,2BAA2B;AAC3B,0BAA0B;AAC1B,cAAc,gCAAgC,CAAC;AAE/C,OAAO,EAAE,KAAK,6BAA6B,EAAE,MAAM,uBAAuB,CAAC;AAC3E,OAAO,QAAQ,uBAAuB,CAAC;IAEnC,UAAiB,mBAAmB;QAClC,uBAAuB,EAAE,6BAA6B,CAAC;KACxD;CAGJ;AACD,OAAO,QAAQ,4BAA4B,CAAC;IAEpC,UAAiB,kBAAkB;KAGlC;IAEC,UAAiB,kBAAkB;QACjC,IAAI,aAAa,IAAI,oCAAoC,CAAC;QAC1D,IAAI,UAAU,IAAI,uBAAuB,CAAC;QAC1C,IAAI,aAAa,IAAI,6BAA6B,CAAC;KACpD;CACV;AACD,wBAAwB;AACxB,kBAAkB;AAClB,cAAc,uBAAuB,CAAC;AAEtC,OAAO,oBAAoB,CAAC;AAC5B,OAAO,QAAQ,oBAAoB,CAAC;IAEhC,UAAiB,WAAW;QAC1B,sBAAsB,EAAE,KAAK,CAAC;KAC/B;CAGJ;AACD,OAAO,QAAQ,4BAA4B,CAAC;IAEpC,UAAiB,SAAS;KAGzB;IAEC,UAAiB,SAAS;QACxB,IAAI,aAAa,IAAI,2BAA2B,CAAC;QACjD,IAAI,UAAU,IAAI,sBAAsB,CAAC;KAE1C;CACV;AACD,gBAAgB;AAChB,wBAAwB;AACxB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACvD,sBAAsB;AACtB,mBAAmB;AACnB,OAAO,EAAE,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,MAAM,CAAC;AAGzD,qBACa,wBAAyB,SAAQ,aAAa;CAAG;AAE9D,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,aAAa,CAAC;IACtB,KAAK,EAAE,SAAS,CAAC;CAChB;AAED,OAAO,MAAM,CAAC;AACd,OAAO,QAAQ,MAAM,CAAC;IACpB,UAAiB,gBAAgB;QAC/B,gBAAgB,EAAE,wBAAwB,CAAC;KAC5C;IAED,UAAiB,mBAAmB;QAClC,aAAa,EAAE,wBAAwB,CAAC;KACzC;CAOF;AACD,iBAAiB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"this.d.ts","sourceRoot":"","sources":["../../src/.metadata/this.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc,mBAAmB,CAAC;AAC/C,OAAO,EAAE,wBAAwB,IAAI,WAAW,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ICaptchaProviderData, ICaptchaProviderExecute, IDecoratorCaptchaProviderOptions } from 'vona-module-a-captcha';
|
|
2
|
+
import { ConfigObject } from '@zhennann/svg-captcha';
|
|
3
|
+
import { BeanBase } from 'vona';
|
|
4
|
+
export type TypeCaptchaProviderImageTextToken = string;
|
|
5
|
+
export type TypeCaptchaProviderImageTextPayload = string;
|
|
6
|
+
export type TypeCaptchaProviderImageTextData = ICaptchaProviderData<TypeCaptchaProviderImageTextToken, TypeCaptchaProviderImageTextPayload>;
|
|
7
|
+
export type TypeCaptchaProviderImageTextType = 'char' | 'math';
|
|
8
|
+
export interface ICaptchaProviderOptionsImageText extends IDecoratorCaptchaProviderOptions {
|
|
9
|
+
type?: TypeCaptchaProviderImageTextType;
|
|
10
|
+
fontPath?: string;
|
|
11
|
+
opts: ConfigObject;
|
|
12
|
+
}
|
|
13
|
+
export declare class CaptchaProviderImageText extends BeanBase implements ICaptchaProviderExecute<TypeCaptchaProviderImageTextToken, TypeCaptchaProviderImageTextPayload> {
|
|
14
|
+
create(options: ICaptchaProviderOptionsImageText): Promise<TypeCaptchaProviderImageTextData>;
|
|
15
|
+
verify(token: TypeCaptchaProviderImageTextToken, tokenInput: TypeCaptchaProviderImageTextToken, _options: ICaptchaProviderOptionsImageText): Promise<boolean>;
|
|
16
|
+
private _confirmFont;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=captchaProvider.imageText.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"captchaProvider.imageText.d.ts","sourceRoot":"","sources":["../../src/bean/captchaProvider.imageText.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,gCAAgC,EAAE,MAAM,uBAAuB,CAAC;AAG7H,OAAmB,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAIjE,OAAO,EAAE,QAAQ,EAAQ,MAAM,MAAM,CAAC;AAGtC,MAAM,MAAM,iCAAiC,GAAG,MAAM,CAAC;AACvD,MAAM,MAAM,mCAAmC,GAAG,MAAM,CAAC;AACzD,MAAM,MAAM,gCAAgC,GAAG,oBAAoB,CAAC,iCAAiC,EAAE,mCAAmC,CAAC,CAAC;AAE5I,MAAM,MAAM,gCAAgC,GAAG,MAAM,GAAG,MAAM,CAAC;AAE/D,MAAM,WAAW,gCAAiC,SAAQ,gCAAgC;IACxF,IAAI,CAAC,EAAE,gCAAgC,CAAC;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,YAAY,CAAC;CACpB;AAED,qBAMa,wBACX,SAAQ,QACR,YAAW,uBAAuB,CAAC,iCAAiC,EAAE,mCAAmC,CAAC;IAEpG,MAAM,CAAC,OAAO,EAAE,gCAAgC,GAAG,OAAO,CAAC,gCAAgC,CAAC;IAU5F,MAAM,CACV,KAAK,EAAE,iCAAiC,EACxC,UAAU,EAAE,iCAAiC,EAC7C,QAAQ,EAAE,gCAAgC,GACzC,OAAO,CAAC,OAAO,CAAC;YAIL,YAAY;CAQ3B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"captchaScene.simple.d.ts","sourceRoot":"","sources":["../../src/bean/captchaScene.simple.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AAGhC,qBAQa,kBAAmB,SAAQ,QAAQ;CAAG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"meta.asset.d.ts","sourceRoot":"","sources":["../../src/bean/meta.asset.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,cAAc,CAAC;CACvB;AAED,qBACa,SAAU,SAAQ,aAAa,CAAC,aAAa,CAAC;CAAG"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { BeanInfo, BeanBase, cast, BeanScopeBase } from 'vona';
|
|
2
|
+
import { __decorate } from 'tslib';
|
|
3
|
+
import { getRandomInt } from '@cabloy/utils';
|
|
4
|
+
import svgCaptcha from '@zhennann/svg-captcha';
|
|
5
|
+
import fse from 'fs-extra';
|
|
6
|
+
import opentype from 'opentype.js';
|
|
7
|
+
import svg64 from 'svg64';
|
|
8
|
+
import { CaptchaProvider, CaptchaScene } from 'vona-module-a-captcha';
|
|
9
|
+
import { Meta } from 'vona-module-a-meta';
|
|
10
|
+
import { BeanAssetBase } from 'vona-module-a-static';
|
|
11
|
+
import { Scope } from 'vona-module-a-bean';
|
|
12
|
+
|
|
13
|
+
const CaptchaProviderImageTextTypes = ['char', 'math'];
|
|
14
|
+
let CaptchaProviderImageText = class CaptchaProviderImageText extends BeanBase {
|
|
15
|
+
async create(options) {
|
|
16
|
+
await this._confirmFont(options);
|
|
17
|
+
let type = options.type;
|
|
18
|
+
if (!type) {
|
|
19
|
+
type = CaptchaProviderImageTextTypes[getRandomInt(2, 0)];
|
|
20
|
+
}
|
|
21
|
+
const captcha = type === 'char' ? svgCaptcha.create(options.opts) : svgCaptcha.createMathExpr(options.opts);
|
|
22
|
+
return {
|
|
23
|
+
token: captcha.text,
|
|
24
|
+
payload: svg64(captcha.data)
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
async verify(token, tokenInput, _options) {
|
|
28
|
+
return !!tokenInput && !!token && tokenInput.toLowerCase() === token.toLowerCase();
|
|
29
|
+
}
|
|
30
|
+
async _confirmFont(options) {
|
|
31
|
+
if (cast(svgCaptcha.options).font) return;
|
|
32
|
+
const fontFile = options.fontPath || this.scope.asset.get('fonts', 'Comismsh.ttf');
|
|
33
|
+
const font = await _loadFont(fontFile);
|
|
34
|
+
cast(svgCaptcha.options).font = font;
|
|
35
|
+
cast(svgCaptcha.options).ascender = font.ascender;
|
|
36
|
+
cast(svgCaptcha.options).descender = font.descender;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
CaptchaProviderImageText = __decorate([CaptchaProvider({
|
|
40
|
+
opts: {
|
|
41
|
+
size: 4,
|
|
42
|
+
color: true
|
|
43
|
+
}
|
|
44
|
+
}), BeanInfo({
|
|
45
|
+
module: "captcha-simple"
|
|
46
|
+
})], CaptchaProviderImageText);
|
|
47
|
+
async function _loadFont(fontFile) {
|
|
48
|
+
const buffer = await fse.readFile(fontFile);
|
|
49
|
+
return opentype.parse(_nodeBufferToArrayBuffer(buffer));
|
|
50
|
+
}
|
|
51
|
+
function _nodeBufferToArrayBuffer(buffer) {
|
|
52
|
+
const ab = new ArrayBuffer(buffer.length);
|
|
53
|
+
const view = new Uint8Array(ab);
|
|
54
|
+
for (let i = 0; i < buffer.length; ++i) {
|
|
55
|
+
view[i] = buffer[i];
|
|
56
|
+
}
|
|
57
|
+
return ab;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
let CaptchaSceneSimple = class CaptchaSceneSimple extends BeanBase {};
|
|
61
|
+
CaptchaSceneSimple = __decorate([CaptchaScene({
|
|
62
|
+
resolver: async (_ctx, _providers) => {
|
|
63
|
+
return 'captcha-simple:imageText';
|
|
64
|
+
},
|
|
65
|
+
providers: {
|
|
66
|
+
'captcha-simple:imageText': true
|
|
67
|
+
}
|
|
68
|
+
}), BeanInfo({
|
|
69
|
+
module: "captcha-simple"
|
|
70
|
+
})], CaptchaSceneSimple);
|
|
71
|
+
|
|
72
|
+
let MetaAsset = class MetaAsset extends BeanAssetBase {};
|
|
73
|
+
MetaAsset = __decorate([Meta(), BeanInfo({
|
|
74
|
+
module: "captcha-simple"
|
|
75
|
+
})], MetaAsset);
|
|
76
|
+
|
|
77
|
+
let ScopeModuleCaptchaSimple = class ScopeModuleCaptchaSimple extends BeanScopeBase {};
|
|
78
|
+
ScopeModuleCaptchaSimple = __decorate([Scope(), BeanInfo({
|
|
79
|
+
module: "captcha-simple"
|
|
80
|
+
})], ScopeModuleCaptchaSimple);
|
|
81
|
+
/** scope: end */
|
|
82
|
+
|
|
83
|
+
export { CaptchaProviderImageText, CaptchaSceneSimple, MetaAsset, ScopeModuleCaptchaSimple };
|
|
84
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/bean/captchaProvider.imageText.ts","../src/bean/captchaScene.simple.ts","../src/bean/meta.asset.ts","../src/.metadata/index.ts"],"sourcesContent":[null,null,null,null],"names":["CaptchaProviderImageTextTypes","CaptchaProviderImageText","BeanBase","create","options","_confirmFont","type","getRandomInt","captcha","svgCaptcha","opts","createMathExpr","token","text","payload","svg64","data","verify","tokenInput","_options","toLowerCase","cast","font","fontFile","fontPath","scope","asset","get","_loadFont","ascender","descender","__decorate","CaptchaProvider","size","color","__z_BeanInfo","module","buffer","fse","readFile","opentype","parse","_nodeBufferToArrayBuffer","ab","ArrayBuffer","length","view","Uint8Array","i","CaptchaSceneSimple","CaptchaScene","resolver","_ctx","_providers","providers","MetaAsset","BeanAssetBase","Meta","ScopeModuleCaptchaSimple","BeanScopeBase","Scope"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "vona-module-captcha-simple",
|
|
3
|
+
"version": "5.1.1",
|
|
4
|
+
"description": "",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"Vona Module"
|
|
7
|
+
],
|
|
8
|
+
"author": "",
|
|
9
|
+
"files": [
|
|
10
|
+
"assets",
|
|
11
|
+
"dist",
|
|
12
|
+
"fonts",
|
|
13
|
+
"src"
|
|
14
|
+
],
|
|
15
|
+
"type": "module",
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"types": [
|
|
19
|
+
"./src/index.ts",
|
|
20
|
+
"./dist/index.d.ts"
|
|
21
|
+
],
|
|
22
|
+
"default": "./dist/index.js"
|
|
23
|
+
},
|
|
24
|
+
"./package.json": "./package.json"
|
|
25
|
+
},
|
|
26
|
+
"scripts": {
|
|
27
|
+
"clean": "rimraf dist tsconfig.build.tsbuildinfo",
|
|
28
|
+
"tsc:publish": "npm run clean && vona :bin:buildModule --sourcemap && tsc -p tsconfig.build.json",
|
|
29
|
+
"prepublishOnly": "npm run tsc:publish",
|
|
30
|
+
"prepack": "clean-package",
|
|
31
|
+
"postpack": "clean-package restore && npm run clean"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@zhennann/svg-captcha": "^1.5.0",
|
|
35
|
+
"opentype.js": "^1.3.4",
|
|
36
|
+
"svg64": "^2.0.0"
|
|
37
|
+
},
|
|
38
|
+
"title": "captcha-simple",
|
|
39
|
+
"vonaModule": {
|
|
40
|
+
"dependencies": {}
|
|
41
|
+
},
|
|
42
|
+
"gitHead": "991189da4443b789fcf77872990b901ccf43bccb"
|
|
43
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// eslint-disable
|
|
2
|
+
/** captchaProvider: begin */
|
|
3
|
+
export * from '../bean/captchaProvider.imageText.ts';
|
|
4
|
+
import type { ICaptchaProviderOptionsImageText } from '../bean/captchaProvider.imageText.ts';
|
|
5
|
+
import 'vona-module-a-captcha';
|
|
6
|
+
declare module 'vona-module-a-captcha' {
|
|
7
|
+
|
|
8
|
+
export interface ICaptchaProviderRecord {
|
|
9
|
+
'captcha-simple:imageText': ICaptchaProviderOptionsImageText;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
}
|
|
14
|
+
declare module 'vona-module-captcha-simple' {
|
|
15
|
+
|
|
16
|
+
export interface CaptchaProviderImageText {
|
|
17
|
+
/** @internal */
|
|
18
|
+
get scope(): ScopeModuleCaptchaSimple;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface CaptchaProviderImageText {
|
|
22
|
+
get $beanFullName(): 'captcha-simple.captchaProvider.imageText';
|
|
23
|
+
get $onionName(): 'captcha-simple:imageText';
|
|
24
|
+
get $onionOptions(): ICaptchaProviderOptionsImageText;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/** captchaProvider: end */
|
|
28
|
+
/** captchaScene: begin */
|
|
29
|
+
export * from '../bean/captchaScene.simple.ts';
|
|
30
|
+
|
|
31
|
+
import { type IDecoratorCaptchaSceneOptions } from 'vona-module-a-captcha';
|
|
32
|
+
declare module 'vona-module-a-captcha' {
|
|
33
|
+
|
|
34
|
+
export interface ICaptchaSceneRecord {
|
|
35
|
+
'captcha-simple:simple': IDecoratorCaptchaSceneOptions;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
}
|
|
40
|
+
declare module 'vona-module-captcha-simple' {
|
|
41
|
+
|
|
42
|
+
export interface CaptchaSceneSimple {
|
|
43
|
+
/** @internal */
|
|
44
|
+
get scope(): ScopeModuleCaptchaSimple;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface CaptchaSceneSimple {
|
|
48
|
+
get $beanFullName(): 'captcha-simple.captchaScene.simple';
|
|
49
|
+
get $onionName(): 'captcha-simple:simple';
|
|
50
|
+
get $onionOptions(): IDecoratorCaptchaSceneOptions;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/** captchaScene: end */
|
|
54
|
+
/** meta: begin */
|
|
55
|
+
export * from '../bean/meta.asset.ts';
|
|
56
|
+
|
|
57
|
+
import 'vona-module-a-meta';
|
|
58
|
+
declare module 'vona-module-a-meta' {
|
|
59
|
+
|
|
60
|
+
export interface IMetaRecord {
|
|
61
|
+
'captcha-simple:asset': never;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
}
|
|
66
|
+
declare module 'vona-module-captcha-simple' {
|
|
67
|
+
|
|
68
|
+
export interface MetaAsset {
|
|
69
|
+
/** @internal */
|
|
70
|
+
get scope(): ScopeModuleCaptchaSimple;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface MetaAsset {
|
|
74
|
+
get $beanFullName(): 'captcha-simple.meta.asset';
|
|
75
|
+
get $onionName(): 'captcha-simple:asset';
|
|
76
|
+
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/** meta: end */
|
|
80
|
+
/** meta asset: begin */
|
|
81
|
+
import type { MetaAsset } from '../bean/meta.asset.ts';
|
|
82
|
+
/** meta asset: end */
|
|
83
|
+
/** scope: begin */
|
|
84
|
+
import { BeanScopeBase, type BeanScopeUtil } from 'vona';
|
|
85
|
+
import { Scope } from 'vona-module-a-bean';
|
|
86
|
+
|
|
87
|
+
@Scope()
|
|
88
|
+
export class ScopeModuleCaptchaSimple extends BeanScopeBase {}
|
|
89
|
+
|
|
90
|
+
export interface ScopeModuleCaptchaSimple {
|
|
91
|
+
util: BeanScopeUtil;
|
|
92
|
+
asset: MetaAsset;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
import 'vona';
|
|
96
|
+
declare module 'vona' {
|
|
97
|
+
export interface IBeanScopeRecord {
|
|
98
|
+
'captcha-simple': ScopeModuleCaptchaSimple;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export interface IBeanScopeContainer {
|
|
102
|
+
captchaSimple: ScopeModuleCaptchaSimple;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
}
|
|
111
|
+
/** scope: end */
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { ICaptchaProviderData, ICaptchaProviderExecute, IDecoratorCaptchaProviderOptions } from 'vona-module-a-captcha';
|
|
2
|
+
|
|
3
|
+
import { getRandomInt } from '@cabloy/utils';
|
|
4
|
+
import svgCaptcha, { ConfigObject } from '@zhennann/svg-captcha';
|
|
5
|
+
import fse from 'fs-extra';
|
|
6
|
+
import opentype from 'opentype.js';
|
|
7
|
+
import svg64 from 'svg64';
|
|
8
|
+
import { BeanBase, cast } from 'vona';
|
|
9
|
+
import { CaptchaProvider } from 'vona-module-a-captcha';
|
|
10
|
+
|
|
11
|
+
export type TypeCaptchaProviderImageTextToken = string;
|
|
12
|
+
export type TypeCaptchaProviderImageTextPayload = string;
|
|
13
|
+
export type TypeCaptchaProviderImageTextData = ICaptchaProviderData<TypeCaptchaProviderImageTextToken, TypeCaptchaProviderImageTextPayload>;
|
|
14
|
+
|
|
15
|
+
export type TypeCaptchaProviderImageTextType = 'char' | 'math';
|
|
16
|
+
const CaptchaProviderImageTextTypes = ['char', 'math'] as const;
|
|
17
|
+
export interface ICaptchaProviderOptionsImageText extends IDecoratorCaptchaProviderOptions {
|
|
18
|
+
type?: TypeCaptchaProviderImageTextType;
|
|
19
|
+
fontPath?: string;
|
|
20
|
+
opts: ConfigObject;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@CaptchaProvider<ICaptchaProviderOptionsImageText>({
|
|
24
|
+
opts: {
|
|
25
|
+
size: 4,
|
|
26
|
+
color: true,
|
|
27
|
+
},
|
|
28
|
+
})
|
|
29
|
+
export class CaptchaProviderImageText
|
|
30
|
+
extends BeanBase
|
|
31
|
+
implements ICaptchaProviderExecute<TypeCaptchaProviderImageTextToken, TypeCaptchaProviderImageTextPayload>
|
|
32
|
+
{
|
|
33
|
+
async create(options: ICaptchaProviderOptionsImageText): Promise<TypeCaptchaProviderImageTextData> {
|
|
34
|
+
await this._confirmFont(options);
|
|
35
|
+
let type = options.type;
|
|
36
|
+
if (!type) {
|
|
37
|
+
type = CaptchaProviderImageTextTypes[getRandomInt(2, 0)];
|
|
38
|
+
}
|
|
39
|
+
const captcha = type === 'char' ? svgCaptcha.create(options.opts) : svgCaptcha.createMathExpr(options.opts);
|
|
40
|
+
return { token: captcha.text, payload: svg64(captcha.data) };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async verify(
|
|
44
|
+
token: TypeCaptchaProviderImageTextToken,
|
|
45
|
+
tokenInput: TypeCaptchaProviderImageTextToken,
|
|
46
|
+
_options: ICaptchaProviderOptionsImageText,
|
|
47
|
+
): Promise<boolean> {
|
|
48
|
+
return !!tokenInput && !!token && tokenInput.toLowerCase() === token.toLowerCase();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
private async _confirmFont(options: ICaptchaProviderOptionsImageText) {
|
|
52
|
+
if (cast(svgCaptcha.options).font) return;
|
|
53
|
+
const fontFile = options.fontPath || this.scope.asset.get('fonts', 'Comismsh.ttf');
|
|
54
|
+
const font = await _loadFont(fontFile);
|
|
55
|
+
cast(svgCaptcha.options).font = font;
|
|
56
|
+
cast(svgCaptcha.options).ascender = font.ascender;
|
|
57
|
+
cast(svgCaptcha.options).descender = font.descender;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async function _loadFont(fontFile: string) {
|
|
62
|
+
const buffer = await fse.readFile(fontFile);
|
|
63
|
+
return opentype.parse(_nodeBufferToArrayBuffer(buffer));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function _nodeBufferToArrayBuffer(buffer) {
|
|
67
|
+
const ab = new ArrayBuffer(buffer.length);
|
|
68
|
+
const view = new Uint8Array(ab);
|
|
69
|
+
for (let i = 0; i < buffer.length; ++i) {
|
|
70
|
+
view[i] = buffer[i];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return ab;
|
|
74
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { BeanBase } from 'vona';
|
|
2
|
+
import { CaptchaScene } from 'vona-module-a-captcha';
|
|
3
|
+
|
|
4
|
+
@CaptchaScene({
|
|
5
|
+
resolver: async (_ctx, _providers) => {
|
|
6
|
+
return 'captcha-simple:imageText';
|
|
7
|
+
},
|
|
8
|
+
providers: {
|
|
9
|
+
'captcha-simple:imageText': true,
|
|
10
|
+
},
|
|
11
|
+
})
|
|
12
|
+
export class CaptchaSceneSimple extends BeanBase {}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './.metadata/index.ts';
|