vona-module-captcha-simple 5.1.13 → 5.1.15

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.
@@ -1 +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"}
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;KAC1C;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"}
@@ -4,6 +4,12 @@ import { BeanBase } from 'vona';
4
4
  export type TypeCaptchaProviderImageTextToken = string;
5
5
  export type TypeCaptchaProviderImageTextPayload = string;
6
6
  export type TypeCaptchaProviderImageTextData = ICaptchaProviderData<TypeCaptchaProviderImageTextToken, TypeCaptchaProviderImageTextPayload>;
7
+ export interface ICaptchaImageTextState {
8
+ token?: string;
9
+ token2?: string;
10
+ revision: string;
11
+ ttlSecondary: number;
12
+ }
7
13
  export type TypeCaptchaProviderImageTextType = 'char' | 'math';
8
14
  export interface ICaptchaProviderOptionsImageText extends IDecoratorCaptchaProviderOptions {
9
15
  type?: TypeCaptchaProviderImageTextType;
@@ -11,8 +17,12 @@ export interface ICaptchaProviderOptionsImageText extends IDecoratorCaptchaProvi
11
17
  opts: ConfigObject;
12
18
  }
13
19
  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>;
20
+ create(options: ICaptchaProviderOptionsImageText, _payload?: unknown, previousToken?: string): Promise<TypeCaptchaProviderImageTextData>;
21
+ verify(token: string, tokenInput: unknown, _options: ICaptchaProviderOptionsImageText): Promise<boolean>;
22
+ verifyImmediate(token: string, tokenInput: unknown, _options: ICaptchaProviderOptionsImageText): Promise<false | string>;
23
+ updateToken(token: string, tokenInput: unknown, options: ICaptchaProviderOptionsImageText): Promise<TypeCaptchaProviderImageTextData>;
24
+ private _matches;
25
+ private _policy;
16
26
  private _confirmFont;
17
27
  }
18
28
  //# sourceMappingURL=captchaProvider.imageText.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"captchaProvider.imageText.d.ts","sourceRoot":"","sources":["../../src/bean/captchaProvider.imageText.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,oBAAoB,EACpB,uBAAuB,EACvB,gCAAgC,EACjC,MAAM,uBAAuB,CAAC;AAG/B,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,CACjE,iCAAiC,EACjC,mCAAmC,CACpC,CAAC;AAEF,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,YACE,uBAAuB,CAAC,iCAAiC,EAAE,mCAAmC,CAAC;IAE3F,MAAM,CACV,OAAO,EAAE,gCAAgC,GACxC,OAAO,CAAC,gCAAgC,CAAC;IAWtC,MAAM,CACV,KAAK,EAAE,iCAAiC,EACxC,UAAU,EAAE,iCAAiC,EAC7C,QAAQ,EAAE,gCAAgC,GACzC,OAAO,CAAC,OAAO,CAAC;YAIL,YAAY;CAQ3B"}
1
+ {"version":3,"file":"captchaProvider.imageText.d.ts","sourceRoot":"","sources":["../../src/bean/captchaProvider.imageText.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,oBAAoB,EACpB,uBAAuB,EACvB,gCAAgC,EACjC,MAAM,uBAAuB,CAAC;AAG/B,OAAmB,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAIjE,OAAO,EAAE,QAAQ,EAAgB,MAAM,MAAM,CAAC;AAG9C,MAAM,MAAM,iCAAiC,GAAG,MAAM,CAAC;AACvD,MAAM,MAAM,mCAAmC,GAAG,MAAM,CAAC;AACzD,MAAM,MAAM,gCAAgC,GAAG,oBAAoB,CACjE,iCAAiC,EACjC,mCAAmC,CACpC,CAAC;AAEF,MAAM,WAAW,sBAAsB;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,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,YACE,uBAAuB,CAAC,iCAAiC,EAAE,mCAAmC,CAAC;IAE3F,MAAM,CACV,OAAO,EAAE,gCAAgC,EACzC,QAAQ,CAAC,EAAE,OAAO,EAClB,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,gCAAgC,CAAC;IAkCtC,MAAM,CACV,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,OAAO,EACnB,QAAQ,EAAE,gCAAgC,GACzC,OAAO,CAAC,OAAO,CAAC;IAmBb,eAAe,CACnB,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,OAAO,EACnB,QAAQ,EAAE,gCAAgC,GACzC,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC;IAmBpB,WAAW,CACf,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,OAAO,EACnB,OAAO,EAAE,gCAAgC,GACxC,OAAO,CAAC,gCAAgC,CAAC;IAwB5C,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,OAAO;YAgBD,YAAY;CAQ3B"}
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { BeanInfo, BeanBase, cast, BeanScopeBase } from 'vona';
1
+ import { BeanInfo, BeanBase, uuidv4, cast, BeanScopeBase } from 'vona';
2
2
  import { __decorate } from 'tslib';
3
3
  import { getRandomInt } from '@cabloy/utils';
4
4
  import svgCaptcha from '@zhennann/svg-captcha';
@@ -12,20 +12,117 @@ import { Scope } from 'vona-module-a-bean';
12
12
 
13
13
  const CaptchaProviderImageTextTypes = ['char', 'math'];
14
14
  let CaptchaProviderImageText = class CaptchaProviderImageText extends BeanBase {
15
- async create(options) {
15
+ async create(options, _payload, previousToken) {
16
+ const cache = this.$scope.captcha.cacheRedis.captcha;
17
+ const snapshot = previousToken ? await cache.snapshot(previousToken) : undefined;
18
+ if (previousToken !== undefined && !previousToken.startsWith('imageText:')) {
19
+ return this.app.throw(403);
20
+ }
21
+ const {
22
+ ttl,
23
+ ttlSecondary
24
+ } = this._policy(options);
16
25
  await this._confirmFont(options);
17
26
  let type = options.type;
18
27
  if (!type) {
19
28
  type = CaptchaProviderImageTextTypes[getRandomInt(2, 0)];
20
29
  }
21
30
  const captcha = type === 'char' ? svgCaptcha.create(options.opts) : svgCaptcha.createMathExpr(options.opts);
22
- return {
31
+ const token = snapshot ? previousToken : `imageText:${uuidv4()}`;
32
+ const written = await cache.writeProof(token, {
23
33
  token: captcha.text,
24
- payload: svg64(captcha.data)
34
+ revision: uuidv4(),
35
+ ttlSecondary
36
+ }, ttl, snapshot);
37
+ if (!written.changed) return this.app.throw(403);
38
+ return {
39
+ token,
40
+ tokenPublic: captcha.text,
41
+ payload: svg64(captcha.data),
42
+ serverNow: written.serverNow,
43
+ expiresAt: written.expiresAt,
44
+ routingExpiresAt: written.expiresAt + ttlSecondary
25
45
  };
26
46
  }
27
47
  async verify(token, tokenInput, _options) {
28
- return !!tokenInput && !!token && tokenInput.toLowerCase() === token.toLowerCase();
48
+ const cache = this.$scope.captcha.cacheRedis.captcha;
49
+ const snapshot = await cache.snapshot(token);
50
+ if (!snapshot || !token.startsWith('imageText:')) return false;
51
+ const data = snapshot.data;
52
+ if (data.token2) {
53
+ const consumed = await cache.compareAndSet(token, snapshot);
54
+ return consumed && data.token2 === tokenInput;
55
+ }
56
+ if (!data.token) return false;
57
+ const verified = this._matches(data.token, tokenInput);
58
+ const changed = await cache.compareAndSet(token, snapshot, verified ? undefined : {
59
+ ...data,
60
+ token: undefined,
61
+ revision: uuidv4()
62
+ });
63
+ return verified && changed;
64
+ }
65
+ async verifyImmediate(token, tokenInput, _options) {
66
+ const cache = this.$scope.captcha.cacheRedis.captcha;
67
+ const snapshot = await cache.snapshot(token);
68
+ if (!snapshot || !token.startsWith('imageText:') || !snapshot.data.token) return false;
69
+ const data = snapshot.data;
70
+ if (!this._matches(data.token, tokenInput)) {
71
+ await cache.compareAndSet(token, snapshot, {
72
+ ...data,
73
+ token: undefined,
74
+ revision: uuidv4()
75
+ });
76
+ return false;
77
+ }
78
+ const tokenSecondary = uuidv4();
79
+ const changed = await cache.compareAndSet(token, snapshot, {
80
+ ...data,
81
+ token: undefined,
82
+ token2: tokenSecondary,
83
+ revision: uuidv4()
84
+ }, data.ttlSecondary);
85
+ return changed ? tokenSecondary : false;
86
+ }
87
+ async updateToken(token, tokenInput, options) {
88
+ const cache = this.$scope.captcha.cacheRedis.captcha;
89
+ const snapshot = await cache.snapshot(token);
90
+ if (!snapshot || !token.startsWith('imageText:') || typeof tokenInput !== 'string') {
91
+ return this.app.throw(403);
92
+ }
93
+ const {
94
+ ttl,
95
+ ttlSecondary
96
+ } = this._policy(options);
97
+ const written = await cache.writeProof(token, {
98
+ token: tokenInput,
99
+ revision: uuidv4(),
100
+ ttlSecondary
101
+ }, ttl, snapshot);
102
+ if (!written.changed) return this.app.throw(403);
103
+ return {
104
+ token,
105
+ tokenPublic: tokenInput,
106
+ payload: '',
107
+ serverNow: written.serverNow,
108
+ expiresAt: written.expiresAt,
109
+ routingExpiresAt: written.expiresAt + ttlSecondary
110
+ };
111
+ }
112
+ _matches(token, input) {
113
+ return typeof input === 'string' && !!input && input.toLowerCase() === token.toLowerCase();
114
+ }
115
+ _policy(options) {
116
+ const defaults = this.$scope.captcha.config.captchaProvider;
117
+ const ttl = options.ttl ?? defaults.ttl;
118
+ const ttlSecondary = options.ttlSecondary ?? defaults.ttlSecondary;
119
+ if (!Number.isSafeInteger(ttl) || ttl <= 0 || !Number.isSafeInteger(ttlSecondary) || ttlSecondary <= 0 || !Number.isSafeInteger(Date.now() + ttl + ttlSecondary)) {
120
+ throw new Error('invalid captcha ttl');
121
+ }
122
+ return {
123
+ ttl,
124
+ ttlSecondary
125
+ };
29
126
  }
30
127
  async _confirmFont(options) {
31
128
  if (cast(svgCaptcha.options).font) return;
package/dist/index.js.map CHANGED
@@ -1 +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","opentypeParse","_nodeBufferToArrayBuffer","ab","ArrayBuffer","length","view","Uint8Array","i","CaptchaSceneSimple","CaptchaScene","resolver","_ctx","_providers","providers","MetaAsset","BeanAssetBase","Meta","ScopeModuleCaptchaSimple","BeanScopeBase","Scope"],"mappings":"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"}
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","_payload","previousToken","cache","$scope","captcha","cacheRedis","snapshot","undefined","startsWith","app","throw","ttl","ttlSecondary","_policy","_confirmFont","type","getRandomInt","svgCaptcha","opts","createMathExpr","token","uuidv4","written","writeProof","text","revision","changed","tokenPublic","payload","svg64","data","serverNow","expiresAt","routingExpiresAt","verify","tokenInput","_options","token2","consumed","compareAndSet","verified","_matches","verifyImmediate","tokenSecondary","updateToken","input","toLowerCase","defaults","config","captchaProvider","Number","isSafeInteger","Date","now","Error","cast","font","fontFile","fontPath","scope","asset","get","_loadFont","ascender","descender","__decorate","CaptchaProvider","size","color","__z_BeanInfo","module","buffer","fse","readFile","opentypeParse","_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 CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "vona-module-captcha-simple",
3
- "version": "5.1.13",
4
- "gitHead": "1a39e8008e1b48001cfeff475ddd53a2a0d867c4",
3
+ "version": "5.1.15",
4
+ "gitHead": "30aa129a2ca0c4ef6dde9cc910d42f7b3982ef79",
5
5
  "description": "",
6
6
  "keywords": [
7
7
  "Vona Module"
@@ -4,15 +4,15 @@ export * from '../bean/captchaProvider.imageText.ts';
4
4
  import type { ICaptchaProviderOptionsImageText } from '../bean/captchaProvider.imageText.ts';
5
5
  import 'vona-module-a-captcha';
6
6
  declare module 'vona-module-a-captcha' {
7
-
7
+
8
8
  export interface ICaptchaProviderRecord {
9
9
  'captcha-simple:imageText': ICaptchaProviderOptionsImageText;
10
10
  }
11
11
 
12
-
12
+
13
13
  }
14
14
  declare module 'vona-module-captcha-simple' {
15
-
15
+
16
16
  export interface CaptchaProviderImageText {
17
17
  /** @internal */
18
18
  get scope(): ScopeModuleCaptchaSimple;
@@ -22,7 +22,7 @@ declare module 'vona-module-captcha-simple' {
22
22
  get $beanFullName(): 'captcha-simple.captchaProvider.imageText';
23
23
  get $onionName(): 'captcha-simple:imageText';
24
24
  get $onionOptions(): ICaptchaProviderOptionsImageText;
25
- }
25
+ }
26
26
  }
27
27
  /** captchaProvider: end */
28
28
  /** captchaScene: begin */
@@ -30,15 +30,15 @@ export * from '../bean/captchaScene.simple.ts';
30
30
 
31
31
  import { type IDecoratorCaptchaSceneOptions } from 'vona-module-a-captcha';
32
32
  declare module 'vona-module-a-captcha' {
33
-
33
+
34
34
  export interface ICaptchaSceneRecord {
35
35
  'captcha-simple:simple': IDecoratorCaptchaSceneOptions;
36
36
  }
37
37
 
38
-
38
+
39
39
  }
40
40
  declare module 'vona-module-captcha-simple' {
41
-
41
+
42
42
  export interface CaptchaSceneSimple {
43
43
  /** @internal */
44
44
  get scope(): ScopeModuleCaptchaSimple;
@@ -48,7 +48,7 @@ declare module 'vona-module-captcha-simple' {
48
48
  get $beanFullName(): 'captcha-simple.captchaScene.simple';
49
49
  get $onionName(): 'captcha-simple:simple';
50
50
  get $onionOptions(): IDecoratorCaptchaSceneOptions;
51
- }
51
+ }
52
52
  }
53
53
  /** captchaScene: end */
54
54
  /** meta: begin */
@@ -56,15 +56,15 @@ export * from '../bean/meta.asset.ts';
56
56
 
57
57
  import 'vona-module-a-meta';
58
58
  declare module 'vona-module-a-meta' {
59
-
59
+
60
60
  export interface IMetaRecord {
61
61
  'captcha-simple:asset': never;
62
62
  }
63
63
 
64
-
64
+
65
65
  }
66
66
  declare module 'vona-module-captcha-simple' {
67
-
67
+
68
68
  export interface MetaAsset {
69
69
  /** @internal */
70
70
  get scope(): ScopeModuleCaptchaSimple;
@@ -73,8 +73,7 @@ declare module 'vona-module-captcha-simple' {
73
73
  export interface MetaAsset {
74
74
  get $beanFullName(): 'captcha-simple.meta.asset';
75
75
  get $onionName(): 'captcha-simple:asset';
76
-
77
- }
76
+ }
78
77
  }
79
78
  /** meta: end */
80
79
  /** meta asset: begin */
@@ -101,11 +100,11 @@ declare module 'vona' {
101
100
  export interface IBeanScopeContainer {
102
101
  captchaSimple: ScopeModuleCaptchaSimple;
103
102
  }
104
-
105
-
106
103
 
107
-
108
104
 
109
-
105
+
106
+
107
+
108
+
110
109
  }
111
110
  /** scope: end */
@@ -9,7 +9,7 @@ import svgCaptcha, { ConfigObject } from '@zhennann/svg-captcha';
9
9
  import fse from 'fs-extra';
10
10
  import { parse as opentypeParse } from 'opentype.js/dist/opentype.mjs';
11
11
  import svg64 from 'svg64';
12
- import { BeanBase, cast } from 'vona';
12
+ import { BeanBase, cast, uuidv4 } from 'vona';
13
13
  import { CaptchaProvider } from 'vona-module-a-captcha';
14
14
 
15
15
  export type TypeCaptchaProviderImageTextToken = string;
@@ -19,6 +19,13 @@ export type TypeCaptchaProviderImageTextData = ICaptchaProviderData<
19
19
  TypeCaptchaProviderImageTextPayload
20
20
  >;
21
21
 
22
+ export interface ICaptchaImageTextState {
23
+ token?: string;
24
+ token2?: string;
25
+ revision: string;
26
+ ttlSecondary: number;
27
+ }
28
+
22
29
  export type TypeCaptchaProviderImageTextType = 'char' | 'math';
23
30
  const CaptchaProviderImageTextTypes = ['char', 'math'] as const;
24
31
  export interface ICaptchaProviderOptionsImageText extends IDecoratorCaptchaProviderOptions {
@@ -40,7 +47,17 @@ export class CaptchaProviderImageText
40
47
  {
41
48
  async create(
42
49
  options: ICaptchaProviderOptionsImageText,
50
+ _payload?: unknown,
51
+ previousToken?: string,
43
52
  ): Promise<TypeCaptchaProviderImageTextData> {
53
+ const cache = this.$scope.captcha.cacheRedis.captcha;
54
+ const snapshot = previousToken
55
+ ? await cache.snapshot<ICaptchaImageTextState>(previousToken)
56
+ : undefined;
57
+ if (previousToken !== undefined && !previousToken.startsWith('imageText:')) {
58
+ return this.app.throw(403);
59
+ }
60
+ const { ttl, ttlSecondary } = this._policy(options);
44
61
  await this._confirmFont(options);
45
62
  let type = options.type;
46
63
  if (!type) {
@@ -48,15 +65,116 @@ export class CaptchaProviderImageText
48
65
  }
49
66
  const captcha =
50
67
  type === 'char' ? svgCaptcha.create(options.opts) : svgCaptcha.createMathExpr(options.opts);
51
- return { token: captcha.text, payload: svg64(captcha.data) };
68
+ const token = snapshot ? previousToken! : `imageText:${uuidv4()}`;
69
+ const written = await cache.writeProof(
70
+ token,
71
+ { token: captcha.text, revision: uuidv4(), ttlSecondary },
72
+ ttl,
73
+ snapshot,
74
+ );
75
+ if (!written.changed) return this.app.throw(403);
76
+ return {
77
+ token,
78
+ tokenPublic: captcha.text,
79
+ payload: svg64(captcha.data),
80
+ serverNow: written.serverNow,
81
+ expiresAt: written.expiresAt,
82
+ routingExpiresAt: written.expiresAt + ttlSecondary,
83
+ };
52
84
  }
53
85
 
54
86
  async verify(
55
- token: TypeCaptchaProviderImageTextToken,
56
- tokenInput: TypeCaptchaProviderImageTextToken,
87
+ token: string,
88
+ tokenInput: unknown,
57
89
  _options: ICaptchaProviderOptionsImageText,
58
90
  ): Promise<boolean> {
59
- return !!tokenInput && !!token && tokenInput.toLowerCase() === token.toLowerCase();
91
+ const cache = this.$scope.captcha.cacheRedis.captcha;
92
+ const snapshot = await cache.snapshot<ICaptchaImageTextState>(token);
93
+ if (!snapshot || !token.startsWith('imageText:')) return false;
94
+ const data = snapshot.data;
95
+ if (data.token2) {
96
+ const consumed = await cache.compareAndSet(token, snapshot);
97
+ return consumed && data.token2 === tokenInput;
98
+ }
99
+ if (!data.token) return false;
100
+ const verified = this._matches(data.token, tokenInput);
101
+ const changed = await cache.compareAndSet(
102
+ token,
103
+ snapshot,
104
+ verified ? undefined : { ...data, token: undefined, revision: uuidv4() },
105
+ );
106
+ return verified && changed;
107
+ }
108
+
109
+ async verifyImmediate(
110
+ token: string,
111
+ tokenInput: unknown,
112
+ _options: ICaptchaProviderOptionsImageText,
113
+ ): Promise<false | string> {
114
+ const cache = this.$scope.captcha.cacheRedis.captcha;
115
+ const snapshot = await cache.snapshot<ICaptchaImageTextState>(token);
116
+ if (!snapshot || !token.startsWith('imageText:') || !snapshot.data.token) return false;
117
+ const data = snapshot.data;
118
+ if (!this._matches(data.token!, tokenInput)) {
119
+ await cache.compareAndSet(token, snapshot, { ...data, token: undefined, revision: uuidv4() });
120
+ return false;
121
+ }
122
+ const tokenSecondary = uuidv4();
123
+ const changed = await cache.compareAndSet(
124
+ token,
125
+ snapshot,
126
+ { ...data, token: undefined, token2: tokenSecondary, revision: uuidv4() },
127
+ data.ttlSecondary,
128
+ );
129
+ return changed ? tokenSecondary : false;
130
+ }
131
+
132
+ async updateToken(
133
+ token: string,
134
+ tokenInput: unknown,
135
+ options: ICaptchaProviderOptionsImageText,
136
+ ): Promise<TypeCaptchaProviderImageTextData> {
137
+ const cache = this.$scope.captcha.cacheRedis.captcha;
138
+ const snapshot = await cache.snapshot<ICaptchaImageTextState>(token);
139
+ if (!snapshot || !token.startsWith('imageText:') || typeof tokenInput !== 'string') {
140
+ return this.app.throw(403);
141
+ }
142
+ const { ttl, ttlSecondary } = this._policy(options);
143
+ const written = await cache.writeProof(
144
+ token,
145
+ { token: tokenInput, revision: uuidv4(), ttlSecondary },
146
+ ttl,
147
+ snapshot,
148
+ );
149
+ if (!written.changed) return this.app.throw(403);
150
+ return {
151
+ token,
152
+ tokenPublic: tokenInput,
153
+ payload: '',
154
+ serverNow: written.serverNow,
155
+ expiresAt: written.expiresAt,
156
+ routingExpiresAt: written.expiresAt + ttlSecondary,
157
+ };
158
+ }
159
+
160
+ private _matches(token: string, input: unknown) {
161
+ return typeof input === 'string' && !!input && input.toLowerCase() === token.toLowerCase();
162
+ }
163
+
164
+ private _policy(options: ICaptchaProviderOptionsImageText) {
165
+ const defaults = this.$scope.captcha.config.captchaProvider;
166
+ const ttl = options.ttl ?? defaults.ttl;
167
+ const ttlSecondary = options.ttlSecondary ?? defaults.ttlSecondary;
168
+ if (
169
+ !Number.isSafeInteger(ttl) ||
170
+ ttl <= 0 ||
171
+ !Number.isSafeInteger(ttlSecondary) ||
172
+ ttlSecondary <= 0 ||
173
+ !Number.isSafeInteger(Date.now() + ttl + ttlSecondary)
174
+ ) {
175
+ throw new Error('invalid captcha ttl');
176
+ }
177
+ return { ttl, ttlSecondary };
60
178
  }
61
179
 
62
180
  private async _confirmFont(options: ICaptchaProviderOptionsImageText) {