forked from leancloud/javascript-sdk
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcaptcha.js
More file actions
142 lines (133 loc) · 4.75 KB
/
Copy pathcaptcha.js
File metadata and controls
142 lines (133 loc) · 4.75 KB
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
const { tap } = require('./utils');
module.exports = (AV) => {
/**
* @class
* @example
* AV.Captcha.request().then(captcha => {
* captcha.bind({
* textInput: 'code', // the id for textInput
* image: 'captcha',
* verifyButton: 'verify',
* }, {
* success: (validateCode) => {}, // next step
* error: (error) => {}, // present error.message to user
* });
* });
*/
AV.Captcha = function Captcha(options, authOptions) {
this._options = options;
this._authOptions = authOptions;
/**
* The image url of the captcha
* @type string
*/
this.url = undefined;
/**
* The captchaToken of the captcha.
* @type string
*/
this.captchaToken = undefined;
/**
* The validateToken of the captcha.
* @type string
*/
this.validateToken = undefined;
};
/**
* Refresh the captcha
* @return {Promise.<string>} a new capcha url
*/
AV.Captcha.prototype.refresh = function refresh() {
return AV.Cloud._requestCaptcha(this._options, this._authOptions).then(({
captchaToken, url,
}) => {
Object.assign(this, { captchaToken, url });
return url;
});
};
/**
* Verify the captcha
* @param {String} code The code from user input
* @return {Promise.<string>} validateToken if the code is valid
*/
AV.Captcha.prototype.verify = function verify(code) {
return AV.Cloud.verifyCaptcha(code, this.captchaToken)
.then(tap(validateToken => (this.validateToken = validateToken)));
};
if (process.env.CLIENT_PLATFORM === 'Browser') {
/**
* Bind the captcha to HTMLElements. <b>ONLY AVAILABLE in browsers</b>.
* @param [elements]
* @param {String|HTMLInputElement} [elements.textInput] An input element typed text, or the id for the element.
* @param {String|HTMLImageElement} [elements.image] An image element, or the id for the element.
* @param {String|HTMLElement} [elements.verifyButton] A button element, or the id for the element.
* @param [callbacks]
* @param {Function} [callbacks.success] Success callback will be called if the code is verified. The param `validateCode` can be used for further SMS request.
* @param {Function} [callbacks.error] Error callback will be called if something goes wrong, detailed in param `error.message`.
*/
AV.Captcha.prototype.bind = function bind({
textInput,
image,
verifyButton,
}, {
success,
error,
}) {
if (typeof textInput === 'string') {
textInput = document.getElementById(textInput);
if (!textInput) throw new Error(`textInput with id ${textInput} not found`);
}
if (typeof image === 'string') {
image = document.getElementById(image);
if (!image) throw new Error(`image with id ${image} not found`);
}
if (typeof verifyButton === 'string') {
verifyButton = document.getElementById(verifyButton);
if (!verifyButton) throw new Error(`verifyButton with id ${verifyButton} not found`);
}
this.__refresh = () => this.refresh().then(url => {
image.src = url;
if (textInput) {
textInput.value = '';
textInput.focus();
}
}).catch(err => console.warn(`refresh captcha fail: ${err.message}`));
if (image) {
this.__image = image;
image.src = this.url;
image.addEventListener('click', this.__refresh);
}
this.__verify = () => {
const code = textInput.value;
this.verify(code).catch(err => {
this.__refresh();
throw err;
}).then(success, error).catch(err => console.warn(`verify captcha fail: ${err.message}`));
};
if (textInput && verifyButton) {
this.__verifyButton = verifyButton;
verifyButton.addEventListener('click', this.__verify);
}
};
/**
* unbind the captcha from HTMLElements. <b>ONLY AVAILABLE in browsers</b>.
*/
AV.Captcha.prototype.unbind = function unbind() {
if (this.__image) this.__image.removeEventListener('click', this.__refresh);
if (this.__verifyButton) this.__verifyButton.removeEventListener('click', this.__verify);
};
}
/**
* Request a captcha
* @param [options]
* @param {Number} [options.width] width(px) of the captcha, ranged 60-200
* @param {Number} [options.height] height(px) of the captcha, ranged 30-100
* @param {Number} [options.size=4] length of the captcha, ranged 3-6. MasterKey required.
* @param {Number} [options.ttl=60] time to live(s), ranged 10-180. MasterKey required.
* @return {Promise.<AV.Captcha>}
*/
AV.Captcha.request = (options, authOptions) => {
const captcha = new AV.Captcha(options, authOptions);
return captcha.refresh().then(() => captcha);
};
};