Skip to content

Commit 8aa34e8

Browse files
authored
feat: captcha (#469)
1 parent 81d9305 commit 8aa34e8

File tree

8 files changed

+137
-95
lines changed

8 files changed

+137
-95
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ coverage
66
*.swp
77
dist/js-sdk-api-docs
88
npm-debug.log
9-
demo/test-es5.js
109
.nyc_output
1110
dist
1211
docs

README.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,6 @@ bower install leancloud-storage --save
3939
* `fork` 这个项目
4040
* `npm install` 安装相关依赖
4141
* 开发和调试
42-
* 浏览器环境执行 `gulp dev`,会自动启动 `demo` 目录,可在 `test-es6.js` 中修改和测试,`test-es5.js` 为自动生成的代码
43-
* Nodejs 环境同样在 `demo` 目录中,通过执行 `node test-es6.js` 开发与调试。推荐安装 `node inspector` 来调试,安装后执行 `node-debug test-es6.js`。每次修改代码后,如果开发代码引用的是 dist 目录中的代码,需要执行 `gulp release`
4442
* 确保测试全部通过 `npm run test`,浏览器环境打开 `test/test.html`
4543
* 提交并发起 `Pull Request`
4644

demo/index.html

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,11 @@ <h1><a href="https://leancloud.cn">LeanCloud</a></h1>
1010
<h2><a href="https://leancloud.cn">为开发加速</a></h2>
1111
<div class="tips">
1212
<p>欢迎调试 JavaScript SDK,请打开浏览器控制台</p>
13+
<img id='captcha' onclick="refreshCaptcha()"/>
14+
<input type="text" id='code'/>
15+
<button onclick="verify()">verify</button>
1316
</div>
1417
<script src="../dist/av.js"></script>
15-
<script src="./test-es5.js"></script>
18+
<script src="./test.js"></script>
1619
</body>
1720
</html>

demo/test-es6.js

Lines changed: 0 additions & 66 deletions
This file was deleted.

demo/test.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
var av = void 0;
2+
3+
// 检测是否在 Nodejs 环境下运行
4+
if (typeof process !== 'undefined' && process.versions && process.versions.node) {
5+
av = require('../dist/node/av');
6+
} else {
7+
av = window.AV;
8+
}
9+
10+
// 初始化
11+
var appId = 'a5CDnmOX94uSth8foK9mjHfq-gzGzoHsz';
12+
var appKey = 'Ue3h6la9zH0IxkUJmyhLjk9h';
13+
var region = 'cn';
14+
15+
// const appId = 'QvNM6AG2khJtBQo6WRMWqfLV-gzGzoHsz';
16+
// const appKey = 'be2YmUduiuEnCB2VR9bLRnnV';
17+
// const region = 'us';
18+
19+
av.init({ appId: appId, appKey: appKey, region: region });
20+
21+
let captchaToken;
22+
const captchaImage = document.getElementById('captcha');
23+
const captchaInput = document.getElementById('code');
24+
25+
function refreshCaptcha(){
26+
AV.Cloud.requestCaptcha({
27+
size: 6,
28+
ttl: 30,
29+
}).then(function(data) {
30+
captchaToken = data.captchaToken;
31+
captchaImage.src = data.url;
32+
}).catch(console.error);
33+
}
34+
refreshCaptcha();
35+
36+
function verify() {
37+
AV.Cloud.verifyCaptcha(captchaInput.value, captchaToken).then(function(validateCode) {
38+
console.log('validateCode: ' + validateCode);
39+
}, console.error);
40+
}

src/cloudfunction.js

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,20 +64,29 @@ module.exports = function(AV) {
6464

6565
/**
6666
* Makes a call to request a sms code for operation verification.
67-
* @param {Object} data The mobile phone number string or a JSON
68-
* object that contains mobilePhoneNumber,template,op,ttl,name etc.
69-
* @return {Promise} A promise that will be resolved with the result
70-
* of the function.
67+
* @param {String|Object} data The mobile phone number string or a JSON
68+
* object that contains mobilePhoneNumber,template,sign,op,ttl,name etc.
69+
* @param {String} data.mobilePhoneNumber
70+
* @param {String} [data.template] sms template name
71+
* @param {String} [data.sign] sms signature name
72+
* @param {AuthOptions} [options] AuthOptions plus:
73+
* @param {String} [options.validateToken] a validate token returned by {@link AV.Cloud.verifyCaptcha}
74+
* @return {Promise} A promise that will be resolved if the request succeed
7175
*/
72-
requestSmsCode: function(data){
76+
requestSmsCode: function(data, options = {}) {
7377
if(_.isString(data)) {
7478
data = { mobilePhoneNumber: data };
7579
}
7680
if(!data.mobilePhoneNumber) {
7781
throw new Error('Missing mobilePhoneNumber.');
7882
}
83+
if (options.validateToken) {
84+
data = _.extend({}, data, {
85+
validate_token: options.validateToken,
86+
});
87+
}
7988
var request = AVRequest("requestSmsCode", null, null, 'POST',
80-
data);
89+
data, options);
8190
return request;
8291
},
8392

@@ -99,6 +108,38 @@ module.exports = function(AV) {
99108
var request = AVRequest("verifySmsCode", code, null, 'POST',
100109
params);
101110
return request;
102-
}
111+
},
112+
113+
/**
114+
* request a captcha
115+
* @param {Object} [options]
116+
* @param {Number} [options.size=4] length of the captcha, ranged 3-6
117+
* @param {Number} [options.width] width(px) of the captcha, ranged 60-200
118+
* @param {Number} [options.height] height(px) of the captcha, ranged 30-100
119+
* @param {Number} [options.ttl=60] time to live(s), ranged 10-180
120+
* @return {Promise} { captchaToken, url }
121+
*/
122+
requestCaptcha(options) {
123+
return AVRequest('requestCaptcha', null, null, 'GET', options).then(({
124+
captcha_url: url,
125+
captcha_token: captchaToken,
126+
}) => ({
127+
captchaToken,
128+
url,
129+
}));
130+
},
131+
132+
/**
133+
* verify captcha code
134+
* @param {String} code the code from user input
135+
* @param {String} captchaToken captchaToken returned by {@link AV.Cloud.requestCaptcha}
136+
* @return {Promise.<String>} validateToken if the code is valid
137+
*/
138+
verifyCaptcha(code, captchaToken) {
139+
return AVRequest('verifyCaptcha', null, null, 'POST', {
140+
captcha_code: code,
141+
captcha_token: captchaToken,
142+
}).then(({ validate_token: validateToken }) => validateToken);
143+
},
103144
});
104145
};

src/user.js

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -899,14 +899,21 @@ module.exports = function(AV) {
899899
* number associated with the user account. This sms code allows the user to
900900
* verify their mobile phone number by calling AV.User.verifyMobilePhone
901901
*
902-
* @param {String} mobilePhone The mobile phone number associated with the
902+
* @param {String} mobilePhoneNumber The mobile phone number associated with the
903903
* user that doesn't verify their mobile phone number.
904+
* @param {AuthOptions} [options] AuthOptions plus:
905+
* @param {String} [options.validateToken] a validate token returned by {@link AV.Cloud.verifyCaptcha}
904906
* @return {Promise}
905907
*/
906-
requestMobilePhoneVerify: function(mobilePhone){
907-
var json = { mobilePhoneNumber: mobilePhone };
908+
requestMobilePhoneVerify: function(mobilePhoneNumber, options = {}){
909+
const data = {
910+
mobilePhoneNumber,
911+
}
912+
if (options.validataToken) {
913+
data.validate_token = options.validataToken
914+
}
908915
var request = AVRequest("requestMobilePhoneVerify", null, null, "POST",
909-
json);
916+
data, options);
910917
return request;
911918
},
912919

@@ -916,14 +923,21 @@ module.exports = function(AV) {
916923
* number associated with the user account. This sms code allows the user to
917924
* reset their account's password by calling AV.User.resetPasswordBySmsCode
918925
*
919-
* @param {String} mobilePhone The mobile phone number associated with the
926+
* @param {String} mobilePhoneNumber The mobile phone number associated with the
920927
* user that doesn't verify their mobile phone number.
928+
* @param {AuthOptions} [options] AuthOptions plus:
929+
* @param {String} [options.validateToken] a validate token returned by {@link AV.Cloud.verifyCaptcha}
921930
* @return {Promise}
922931
*/
923-
requestPasswordResetBySmsCode: function(mobilePhone){
924-
var json = { mobilePhoneNumber: mobilePhone };
932+
requestPasswordResetBySmsCode: function(mobilePhoneNumber, options = {}){
933+
const data = {
934+
mobilePhoneNumber,
935+
}
936+
if (options.validataToken) {
937+
data.validate_token = options.validataToken
938+
}
925939
var request = AVRequest("requestPasswordResetBySmsCode", null, null, "POST",
926-
json);
940+
data, options);
927941
return request;
928942
},
929943

@@ -960,14 +974,21 @@ module.exports = function(AV) {
960974
* number associated with the user account. This sms code allows the user to
961975
* login by AV.User.logInWithMobilePhoneSmsCode function.
962976
*
963-
* @param {String} mobilePhone The mobile phone number associated with the
977+
* @param {String} mobilePhoneNumber The mobile phone number associated with the
964978
* user that want to login by AV.User.logInWithMobilePhoneSmsCode
979+
* @param {AuthOptions} [options] AuthOptions plus:
980+
* @param {String} [options.validateToken] a validate token returned by {@link AV.Cloud.verifyCaptcha}
965981
* @return {Promise}
966982
*/
967-
requestLoginSmsCode: function(mobilePhone){
968-
var json = { mobilePhoneNumber: mobilePhone };
983+
requestLoginSmsCode: function(mobilePhoneNumber, options = {}){
984+
const data = {
985+
mobilePhoneNumber,
986+
}
987+
if (options.validataToken) {
988+
data.validate_token = options.validataToken
989+
}
969990
var request = AVRequest("requestLoginSmsCode", null, null, "POST",
970-
json);
991+
data, options);
971992
return request;
972993
},
973994

storage.d.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ declare namespace AV {
1717
user?: User;
1818
}
1919

20+
interface SMSAuthOptions extends AuthOptions {
21+
validateToken?: string;
22+
}
23+
2024
export interface WaitOption {
2125
/**
2226
* Set to true to wait for the server to confirm success
@@ -508,10 +512,10 @@ declare namespace AV {
508512
static signUpOrlogInWithAuthData<T>(data: any, platform: string, options?: AuthOptions): Promise<T>;
509513
static signUpOrlogInWithMobilePhone<T>(mobilePhoneNumber: string, smsCode: string, attributes?: any, options?: AuthOptions): Promise<T>;
510514
static requestEmailVerify<T>(email: string, options?: AuthOptions): Promise<T>;
511-
static requestLoginSmsCode<T>(mobilePhone: string, options?: AuthOptions): Promise<T>;
512-
static requestMobilePhoneVerify<T>(mobilePhone: string, options?: AuthOptions): Promise<T>;
515+
static requestLoginSmsCode(mobilePhoneNumber: string, options?: SMSAuthOptions): Promise<void>;
516+
static requestMobilePhoneVerify(mobilePhoneNumber: string, options?: SMSAuthOptions): Promise<void>;
513517
static requestPasswordReset<T>(email: string, options?: AuthOptions): Promise<T>;
514-
static requestPasswordResetBySmsCode<T>(mobilePhone: string, options?: AuthOptions): Promise<T>;
518+
static requestPasswordResetBySmsCode(mobilePhoneNumber: string, options?: SMSAuthOptions): Promise<void>;
515519
static resetPasswordBySmsCode<T>(code: string, password: string, options?: AuthOptions): Promise<T>;
516520
static verifyMobilePhone<T>(code: string, options?: AuthOptions): Promise<T>;
517521
signUp<T>(attrs?: any, options?: AuthOptions): Promise<T>;
@@ -673,9 +677,11 @@ declare namespace AV {
673677
}
674678

675679
export namespace Cloud {
676-
function run<T>(name: string, data?: any, options?: AuthOptions): Promise<T>;
677-
function requestSmsCode<T>(data: any, options?: AuthOptions): Promise<T>;
678-
function verifySmsCode<T>(code: string, phone: string, options?: AuthOptions): Promise<T>;
680+
function run(name: string, data?: any, options?: AuthOptions): Promise<any>;
681+
function requestSmsCode(data: string|{ mobilePhoneNumber: string, template?: string, sign?: string }, options?: SMSAuthOptions): Promise<void>;
682+
function verifySmsCode(code: string, phone: string): Promise<void>;
683+
function requestCaptcha(options?: { size?: number, width?: number, height?: number, ttl?: number}): Promise<{ captchaToken: string, dataURI: string }>;
684+
function verifyCaptcha(code: string, captchaToken: string): Promise<void>;
679685
}
680686

681687
/**

0 commit comments

Comments
 (0)