[WO-587] implement user logout

This commit is contained in:
Tankred Hase 2014-09-26 19:14:53 +02:00
parent f66fbf592c
commit bedb69973c
8 changed files with 190 additions and 59 deletions

View File

@ -32,7 +32,7 @@ define(function(require) {
var self = {};
/**
* Start the application
* Start the application.
*/
self.start = function(options, callback) {
if (self.started) {
@ -66,6 +66,9 @@ define(function(require) {
}
};
/**
* Initialize the dependency tree.
*/
self.buildModules = function() {
var lawnchairDao, restDao, pubkeyDao, privkeyDao, crypto, emailDao, keychain, pgp, userStorage, pgpbuilder, oauth, appConfigStore, auth;
@ -110,14 +113,101 @@ define(function(require) {
emailDao.onError = self.onError;
};
/**
* Calls runtime hooks to check if an app update is available.
*/
self.checkForUpdate = function() {
self._updateHandler.checkForUpdate(self.onError);
};
/**
* Instanciate the mail email data access object and its dependencies. Login to imap on init.
*/
self.init = function(options, callback) {
// init user's local database
self._userStorage.init(options.emailAddress, function(err) {
if (err) {
callback(err);
return;
}
// Migrate the databases if necessary
self._updateHandler.update(onUpdate);
});
function onUpdate(err) {
if (err) {
callback({
errMsg: 'Update failed, please reinstall the app.',
err: err
});
return;
}
// account information for the email dao
var account = {
realname: options.realname,
emailAddress: options.emailAddress,
asymKeySize: config.asymKeySize
};
// init email dao
self._emailDao.init({
account: account
}, function(err, keypair) {
if (err) {
callback(err);
return;
}
callback(null, keypair);
});
}
};
/**
* Check if the user agent is online.
*/
self.isOnline = function() {
return navigator.onLine;
};
/**
* Event handler that is called when the user agent goes offline.
*/
self.onDisconnect = function() {
self._emailDao.onDisconnect();
};
/**
* Log the current user out by clear the app config store and deleting instances of imap-client and pgp-mailer.
*/
self.logout = function() {
var self = this;
// clear app config store
self._auth.logout(function(err) {
if (err) {
self.onError(err);
return;
}
// delete instance of imap-client and pgp-mailer
self._emailDao.onDisconnect(function(err) {
if (err) {
self.onError(err);
return;
}
// navigate to login
window.location.href = '/';
});
});
};
/**
* Event that is called when the user agent goes online. This create new instances of the imap-client and pgp-mailer and connects to the mail server.
*/
self.onConnect = function(callback) {
if (!self.isOnline() || !self._emailDao || !self._emailDao._account) {
// prevent connection infinite loop
@ -174,54 +264,5 @@ define(function(require) {
}
};
self.checkForUpdate = function() {
self._updateHandler.checkForUpdate(self.onError);
};
/**
* Instanciate the mail email data access object and its dependencies. Login to imap on init.
*/
self.init = function(options, callback) {
// init user's local database
self._userStorage.init(options.emailAddress, function(err) {
if (err) {
callback(err);
return;
}
// Migrate the databases if necessary
self._updateHandler.update(onUpdate);
});
function onUpdate(err) {
if (err) {
callback({
errMsg: 'Update failed, please reinstall the app.',
err: err
});
return;
}
// account information for the email dao
var account = {
realname: options.realname,
emailAddress: options.emailAddress,
asymKeySize: config.asymKeySize
};
// init email dao
self._emailDao.init({
account: account
}, function(err, keypair) {
if (err) {
callback(err);
return;
}
callback(null, keypair);
});
}
};
return self;
});

View File

@ -426,5 +426,28 @@ define(function(require) {
});
};
/**
* Logout of the app by clearing the app config store and in memory credentials
*/
Auth.prototype.logout = function(callback) {
var self = this;
// clear app config db
self._appConfigStore.clear(function(err) {
if (err) {
callback(err);
return;
}
// clear in memory cache
self.setCredentials({});
self.initialized = undefined;
self.credentialsDirty = undefined;
self.passwordNeedsDecryption = undefined;
callback();
});
};
return Auth;
});

View File

@ -56,6 +56,19 @@ define(function(require) {
}, $scope.onError);
};
$scope.logout = function() {
$scope.onError({
title: 'Logout',
message: 'Are you sure you want to logout?',
callback: function(confirm) {
if (confirm) {
appController.logout();
}
},
sync: true
});
};
//
// Start
//

View File

@ -1206,13 +1206,24 @@ define(function(require) {
};
/**
* This handler should be invoked when navigator.onLine === false. It will discard
* the imap client and pgp mailer
* This handler should be invoked when navigator.onLine === false.
* It will discard the imap client and pgp mailer
*/
EmailDAO.prototype.onDisconnect = function() {
this._account.online = false;
this._imapClient = undefined;
this._pgpMailer = undefined;
EmailDAO.prototype.onDisconnect = function(callback) {
var self = this;
// logout of imap-client
self._imapClient.logout(function() {
// ignore error, because it's not problem if logout fails
if (callback) {
callback();
}
});
// discard clients
self._account.online = false;
self._imapClient = undefined;
self._pgpMailer = undefined;
};
/**

View File

@ -20,6 +20,7 @@
<li><a href="#" wo-touch="state.privateKeyUpload.toggle(true); $event.preventDefault()">Key sync (experimental)</a></li>
<li><a href="#" wo-touch="state.writer.reportBug(); $event.preventDefault()">Report a bug</a></li>
<li><a href="#" wo-touch="state.about.toggle(true); $event.preventDefault()">About</a></li>
<li><a href="#" wo-touch="logout(); $event.preventDefault()">Logout</a></li>
</ul>
<footer>

View File

@ -64,6 +64,22 @@ define(function(require) {
});
});
describe('logout', function() {
it('should work', function(done) {
authStub.logout.yields();
emailDaoStub.onDisconnect.yields(new Error());
controller.onError = function(err) {
expect(err).to.exist;
expect(authStub.logout.calledOnce).to.be.true;
expect(emailDaoStub.onDisconnect.calledOnce).to.be.true;
done();
};
controller.logout();
});
});
describe('onConnect', function() {
beforeEach(function() {
controller._emailDao._account = {};

View File

@ -350,5 +350,29 @@ define(function(require) {
auth.handleCertificateUpdate('imap', onConnect, callback, dummyCert);
});
});
describe('#logout', function() {
it('should fail to to error in calling db clear', function(done) {
storageStub.clear.yields(new Error());
auth.logout(function(err) {
expect(err).to.exist;
done();
});
});
it('should work', function(done) {
storageStub.clear.yields();
auth.logout(function(err) {
expect(err).to.not.exist;
expect(auth.password).to.be.undefined;
expect(auth.initialized).to.be.undefined;
expect(auth.credentialsDirty).to.be.undefined;
expect(auth.passwordNeedsDecryption).to.be.undefined;
done();
});
});
});
});
});

View File

@ -446,7 +446,7 @@ define(function(require) {
it('should not notify for other folders', function(done) {
opts.folder = sentFolder;
imapListStub.withArgs(opts).yieldsAsync(null, [message]);
localStoreStub.withArgs({
@ -1774,8 +1774,10 @@ define(function(require) {
});
describe('#onDisconnect', function() {
it('should discard imapClient and pgpMailer', function() {
dao.onDisconnect();
it('should discard imapClient and pgpMailer', function(done) {
imapClientStub.logout.yieldsAsync();
dao.onDisconnect(done);
expect(dao._account.online).to.be.false;
expect(dao._imapClient).to.not.exist;