1
0
mirror of https://github.com/moparisthebest/mail synced 2025-02-20 04:41:52 -05:00

Add SMS validation

This commit is contained in:
Tankred Hase 2014-09-19 18:59:13 +02:00
parent 7c7d650cf2
commit d1308aa14c
6 changed files with 198 additions and 17 deletions

View File

@ -29,12 +29,38 @@ define(function(require) {
appCtrl._adminDao.createUser({ appCtrl._adminDao.createUser({
emailAddress: $scope.emailAddress, emailAddress: $scope.emailAddress,
password: $scope.pass, password: $scope.pass,
//phone: $scope.phone, phone: $scope.phone,
//betaCode: $scope.betaCode betaCode: $scope.betaCode.toUpperCase()
}, function(err) {
$scope.busy = false;
if (err) {
$scope.errMsg = err.errMsg || err.message;
$scope.$apply();
return;
}
$scope.goTo(3);
$scope.$apply();
});
};
$scope.validateUser = function() {
if ($scope.formValidate.$invalid) {
return;
}
$scope.busyValidate = true;
$scope.errMsgValidate = undefined; // reset error msg
// verify user to REST api
appCtrl._adminDao.validateUser({
emailAddress: $scope.emailAddress,
token: $scope.token.toUpperCase()
}, function(err) { }, function(err) {
if (err) { if (err) {
$scope.busy = false; $scope.busyValidate = false;
$scope.errMsg = err.errMsg || err.message; $scope.errMsgValidate = err.errMsg || err.message;
$scope.$apply(); $scope.$apply();
return; return;
} }

View File

@ -15,7 +15,7 @@ define(function() {
AdminDAO.prototype.createUser = function(options, callback) { AdminDAO.prototype.createUser = function(options, callback) {
var uri; var uri;
if (!options.emailAddress || !options.password /* || !options.phone*/ ) { if (!options.emailAddress || !options.password || !options.phone) {
callback(new Error('Incomplete arguments!')); callback(new Error('Incomplete arguments!'));
return; return;
} }
@ -34,5 +34,30 @@ define(function() {
}); });
}; };
/**
* Verify a user's phone number by confirming a token to the server.
* @param {String} options.emailAddress The desired email address
* @param {String} options.token The validation token.
* @param {Function} callback(error)
*/
AdminDAO.prototype.validateUser = function(options, callback) {
var uri;
if (!options.emailAddress || !options.token) {
callback(new Error('Incomplete arguments!'));
return;
}
uri = '/user/validate';
this._restDao.post(options, uri, function(err) {
if (!err || (err && err.code === 202)) {
// success
callback();
} else {
callback(new Error('Validation failed!'));
}
});
};
return AdminDAO; return AdminDAO;
}); });

View File

@ -78,6 +78,10 @@
width: 100%; width: 100%;
} }
input.token {
width: auto;
}
input[type=file] { input[type=file] {
width: 100%; width: 100%;
background-color: white; background-color: white;
@ -142,10 +146,6 @@
margin-top: 20px; margin-top: 20px;
} }
input.token {
width: auto;
}
.code { .code {
max-width: 240px; max-width: 240px;
margin: 0 auto; margin: 0 auto;

View File

@ -13,7 +13,7 @@
<hr> <hr>
<div class="choice"> <div class="choice">
<p><b>Login to IMAP account.</b> Connect Whiteout Mail to any existing email account via IMAP.</p> <p><b>Login to IMAP account.</b> Connect Whiteout Mail to any existing email account via IMAP.</p>
<button class="btn btn-alt" wo-touch="goTo(3)">Login to existing</button> <button class="btn btn-alt" wo-touch="goTo(4)">Login to existing</button>
</div> </div>
</div> </div>
</div> </div>
@ -29,7 +29,7 @@
<label class="input-error-message" ng-show="errMsg">{{errMsg}}</label> <label class="input-error-message" ng-show="errMsg">{{errMsg}}</label>
<label class="input-error-message" ng-show="form.$invalid">Please fill out all required fields!</label> <label class="input-error-message" ng-show="form.$invalid">Please fill out all required fields!</label>
<div class="flex"> <div class="flex">
<input class="input-text wmail" ng-model="user" required type="text" pattern='^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))' placeholder="User name"> <input class="input-text wmail" ng-model="user" required type="text" pattern='^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))' placeholder="User name" focus-me="step === 2">
<span class="domain">@wmail.io</span> <span class="domain">@wmail.io</span>
</div> </div>
<input class="input-text" type="text" ng-model="realname" placeholder="Full name (optional)"></input> <input class="input-text" type="text" ng-model="realname" placeholder="Full name (optional)"></input>
@ -51,7 +51,30 @@
</div> </div>
</div> </div>
<div class="providers" ng-show="step === 3"> <div ng-show="step === 3">
<div class="logo">
<img src="img/whiteout_logo.svg" alt="whiteout.io">
</div><!--/logo-->
<div class="content">
<p><b>Validate phone number.</b> We have sent you a validation code via SMS. Please enter this code to confirm your phone number.</p>
<form name="formValidate">
<label class="input-error-message" ng-show="errMsgValidate">{{errMsgValidate}}</label>
<br>
<input type="text" class="input-text token" size="6" maxlength="6" ng-model="token" placeholder="Code" focus-me="step === 3" required pattern="([a-zA-Z0-9]*)">
<div class="working" ng-show="busyValidate">
<span class="spinner"></span>
</div>
<div>
<button class="btn" type="submit" ng-click="validateUser()">Confirm code</button>
</div>
</form>
</div>
</div>
<div class="providers" ng-show="step === 4">
<h1>Select account</h1> <h1>Select account</h1>
<ul> <ul>

View File

@ -25,6 +25,7 @@ define(function(require) {
scope = $rootScope.$new(); scope = $rootScope.$new();
scope.state = {}; scope.state = {};
scope.form = {}; scope.form = {};
scope.formValidate = {};
sinon.stub(location, 'path').returns(location); sinon.stub(location, 'path').returns(location);
sinon.stub(location, 'search').returns(location); sinon.stub(location, 'search').returns(location);
@ -58,6 +59,7 @@ define(function(require) {
it('should fail to error creating user', function(done) { it('should fail to error creating user', function(done) {
scope.form.$invalid = false; scope.form.$invalid = false;
scope.betaCode = 'asfd';
adminStub.createUser.yieldsAsync(new Error('asdf')); adminStub.createUser.yieldsAsync(new Error('asdf'));
scope.$apply = function() { scope.$apply = function() {
@ -73,11 +75,13 @@ define(function(require) {
it('should work', function(done) { it('should work', function(done) {
scope.form.$invalid = false; scope.form.$invalid = false;
scope.betaCode = 'asfd';
adminStub.createUser.yieldsAsync(); adminStub.createUser.yieldsAsync();
scope.login = function() { scope.$apply = function() {
expect(scope.busy).to.be.true; expect(scope.busy).to.be.false;
expect(scope.errMsg).to.be.undefined; expect(scope.errMsg).to.be.undefined;
expect(scope.step).to.equal(3);
expect(adminStub.createUser.calledOnce).to.be.true; expect(adminStub.createUser.calledOnce).to.be.true;
done(); done();
}; };
@ -87,6 +91,46 @@ define(function(require) {
}); });
}); });
describe('validateUser', function() {
it('should return early for invalid form', function() {
scope.formValidate.$invalid = true;
scope.validateUser();
expect(adminStub.validateUser.called).to.be.false;
});
it('should fail to error creating user', function(done) {
scope.formValidate.$invalid = false;
scope.token = 'asfd';
adminStub.validateUser.yieldsAsync(new Error('asdf'));
scope.$apply = function() {
expect(scope.busyValidate).to.be.false;
expect(scope.errMsgValidate).to.equal('asdf');
expect(adminStub.validateUser.calledOnce).to.be.true;
done();
};
scope.validateUser();
expect(scope.busyValidate).to.be.true;
});
it('should work', function(done) {
scope.formValidate.$invalid = false;
scope.token = 'asfd';
adminStub.validateUser.yieldsAsync();
scope.login = function() {
expect(scope.busyValidate).to.be.true;
expect(scope.errMsgValidate).to.be.undefined;
expect(adminStub.validateUser.calledOnce).to.be.true;
done();
};
scope.validateUser();
expect(scope.busyValidate).to.be.true;
});
});
describe('login', function() { describe('login', function() {
it('should work', function() { it('should work', function() {
scope.form.$invalid = false; scope.form.$invalid = false;

View File

@ -33,7 +33,8 @@ define(function(require) {
it('should fail if user already exists', function(done) { it('should fail if user already exists', function(done) {
var opt = { var opt = {
emailAddress: emailAddress, emailAddress: emailAddress,
password: password password: password,
phone: '12345'
}; };
restDaoStub.post.withArgs(opt, '/user').yields({ restDaoStub.post.withArgs(opt, '/user').yields({
@ -50,7 +51,8 @@ define(function(require) {
it('should fail due to unknown error', function(done) { it('should fail due to unknown error', function(done) {
var opt = { var opt = {
emailAddress: emailAddress, emailAddress: emailAddress,
password: password password: password,
phone: '12345'
}; };
restDaoStub.post.withArgs(opt, '/user').yields(new Error()); restDaoStub.post.withArgs(opt, '/user').yields(new Error());
@ -65,7 +67,8 @@ define(function(require) {
it('should work', function(done) { it('should work', function(done) {
var opt = { var opt = {
emailAddress: emailAddress, emailAddress: emailAddress,
password: password password: password,
phone: '12345'
}; };
restDaoStub.post.withArgs(opt, '/user').yields(); restDaoStub.post.withArgs(opt, '/user').yields();
@ -78,6 +81,66 @@ define(function(require) {
}); });
}); });
describe('validateUser', function() {
it('should fail due to incomplete args', function(done) {
var opt = {
emailAddress: emailAddress
};
adminDao.validateUser(opt, function(err) {
expect(err).to.exist;
done();
});
});
it('should fail due to error in rest api', function(done) {
var opt = {
emailAddress: emailAddress,
token: 'H45Z6D'
};
restDaoStub.post.withArgs(opt, '/user/validate').yields(new Error());
adminDao.validateUser(opt, function(err) {
expect(err).to.exist;
expect(restDaoStub.post.calledOnce).to.be.true;
done();
});
});
it('should work with no error object', function(done) {
var opt = {
emailAddress: emailAddress,
token: 'H45Z6D'
};
restDaoStub.post.withArgs(opt, '/user/validate').yields();
adminDao.validateUser(opt, function(err) {
expect(err).to.not.exist;
expect(restDaoStub.post.calledOnce).to.be.true;
done();
});
});
it('should work with 202', function(done) {
var opt = {
emailAddress: emailAddress,
token: 'H45Z6D'
};
restDaoStub.post.withArgs(opt, '/user/validate').yields({
code: 202
});
adminDao.validateUser(opt, function(err) {
expect(err).to.not.exist;
expect(restDaoStub.post.calledOnce).to.be.true;
done();
});
});
});
}); });
}); });