1
0
mirror of https://github.com/moparisthebest/mail synced 2024-11-26 10:52:17 -05:00

list and store only encrypted emails in local db

This commit is contained in:
Tankred Hase 2013-09-28 19:04:15 +02:00
parent 7eb885c679
commit 267e889872
8 changed files with 178 additions and 35 deletions

View File

@ -52,6 +52,7 @@ define(function(require) {
// development // development
createDummyMails(function(emails) { createDummyMails(function(emails) {
updateStatus('Last update: ', new Date());
$scope.emails = emails; $scope.emails = emails;
$scope.select($scope.emails[0]); $scope.select($scope.emails[0]);
}); });

View File

@ -30,7 +30,6 @@ define(function(require) {
callback(); callback();
return; return;
} }
// validate type // validate type
if (!type) { if (!type) {
callback({ callback({
@ -41,16 +40,7 @@ define(function(require) {
// format items for batch storing in dao // format items for batch storing in dao
list.forEach(function(i) { list.forEach(function(i) {
// put uid in key if available... for easy querying key = createKey(i, type);
if (i.uid) {
key = type + '_' + i.uid;
} else if (i.sentDate && i.id) {
key = type + '_' + i.sentDate + '_' + i.id;
} else if (i.id) {
key = type + '_' + i.id;
} else {
key = type;
}
items.push({ items.push({
key: key, key: key,
@ -63,6 +53,23 @@ define(function(require) {
}); });
}; };
/**
* Deletes items of a certain type from storage
*/
DeviceStorageDAO.prototype.removeList = function(type, callback) {
// validate type
if (!type) {
callback({
errMsg: 'Type is not set!'
});
return;
}
jsonDao.removeList(type, function() {
callback();
});
};
/** /**
* List stored items of a given type * List stored items of a given type
* @param type [String] The type of item e.g. 'email' * @param type [String] The type of item e.g. 'email'
@ -70,10 +77,18 @@ define(function(require) {
* @param num [Number] The number of items to fetch (null means fetch all) * @param num [Number] The number of items to fetch (null means fetch all)
*/ */
DeviceStorageDAO.prototype.listItems = function(type, offset, num, callback) { DeviceStorageDAO.prototype.listItems = function(type, offset, num, callback) {
// fetch all items of a certain type from the data-store
jsonDao.list(type, offset, num, function(encryptedList) {
callback(null, encryptedList); // validate type
if (!type || typeof offset === 'undefined' || typeof num === 'undefined') {
callback({
errMsg: 'Args not is not set!'
});
return;
}
// fetch all items of a certain type from the data-store
jsonDao.list(type, offset, num, function(matchingList) {
callback(null, matchingList);
}); });
}; };
@ -84,5 +99,26 @@ define(function(require) {
jsonDao.clear(callback); jsonDao.clear(callback);
}; };
//
// helper functions
//
function createKey(i, type) {
var key;
// put uid in key if available... for easy querying
if (i.uid) {
key = type + '_' + i.uid;
} else if (i.sentDate && i.id) {
key = type + '_' + i.sentDate + '_' + i.id;
} else if (i.id) {
key = type + '_' + i.id;
} else {
key = type;
}
return key;
}
return DeviceStorageDAO; return DeviceStorageDAO;
}); });

View File

@ -400,7 +400,8 @@ define(function(require) {
* High level sync operation for the delta from the user's IMAP inbox * High level sync operation for the delta from the user's IMAP inbox
*/ */
EmailDAO.prototype.imapSync = function(options, callback) { EmailDAO.prototype.imapSync = function(options, callback) {
var self = this; var self = this,
dbType = 'email_' + options.folder;
// validate options // validate options
if (!options.folder || typeof options.offset === 'undefined' || typeof options.num === 'undefined') { if (!options.folder || typeof options.offset === 'undefined' || typeof options.num === 'undefined') {
@ -411,13 +412,22 @@ define(function(require) {
} }
fetchList(options, function(emails) { fetchList(options, function(emails) {
// delete old items from db
self._devicestorage.removeList(dbType, function(err) {
if (err) {
callback(err);
return;
}
// persist encrypted list in device storage // persist encrypted list in device storage
self._devicestorage.storeList(emails, 'email_' + options.folder, function() { self._devicestorage.storeList(emails, dbType, function(err) {
callback(); callback(err);
});
}); });
}); });
function fetchList(folder, callback) { function fetchList(folder, callback) {
var encryptedList = [];
// fetch imap folder's message list // fetch imap folder's message list
self.imapListMessages({ self.imapListMessages({
folder: options.folder, folder: options.folder,
@ -429,8 +439,15 @@ define(function(require) {
return; return;
} }
// find encrypted messages by subject
emails.forEach(function(i) {
if (i.subject === str.subject) {
encryptedList.push(i);
}
});
// fetch message bodies // fetch message bodies
fetchBodies(emails, folder, function(messages) { fetchBodies(encryptedList, folder, function(messages) {
callback(messages); callback(messages);
}); });
}); });
@ -439,6 +456,11 @@ define(function(require) {
function fetchBodies(messageList, folder, callback) { function fetchBodies(messageList, folder, callback) {
var emails = []; var emails = [];
if (messageList.length < 1) {
callback(emails);
return;
}
var after = _.after(messageList.length, function() { var after = _.after(messageList.length, function() {
callback(emails); callback(emails);
}); });

View File

@ -1,7 +1,7 @@
/** /**
* Handles generic caching of JSON objects in a lawnchair adapter * Handles generic caching of JSON objects in a lawnchair adapter
*/ */
define(['lawnchair', 'lawnchairSQL', 'lawnchairIDB'], function(Lawnchair) { define(['underscore', 'lawnchair', 'lawnchairSQL', 'lawnchairIDB'], function(_, Lawnchair) {
'use strict'; 'use strict';
var self = {}, var self = {},
@ -118,6 +118,35 @@ define(['lawnchair', 'lawnchairSQL', 'lawnchairIDB'], function(Lawnchair) {
db.remove(key, callback); db.remove(key, callback);
}; };
/**
* Removes an object liter from local storage by its key (delete)
*/
self.removeList = function(type, callback) {
var matchingKeys = [],
after;
// get all keys
db.keys(function(keys) {
// check if key begins with type
keys.forEach(function(key) {
if (key.indexOf(type) === 0) {
matchingKeys.push(key);
}
});
if (matchingKeys.length < 1) {
callback();
return;
}
// remove all matching keys
after = _.after(matchingKeys.length, callback);
_.each(matchingKeys, function(key) {
db.remove(key, after);
});
});
};
/** /**
* Clears the whole local storage cache * Clears the whole local storage cache
*/ */

View File

@ -35,8 +35,8 @@
} }
ul { ul {
padding: 0 $padding-horizontal; padding: 0 $padding-horizontal 90px $padding-horizontal;
max-height: 100%; height: 100%;
overflow-y: scroll; overflow-y: scroll;
} }

View File

@ -367,7 +367,7 @@ define(function(require) {
}); });
describe('IMAP: sync messages to local storage', function() { describe('IMAP: sync messages to local storage', function() {
it('should work', function(done) { it('should not list unencrypted messages', function(done) {
imapClientStub.listMessages.yields(null, [{ imapClientStub.listMessages.yields(null, [{
uid: 413, uid: 413,
}, { }, {
@ -376,6 +376,35 @@ define(function(require) {
imapClientStub.getMessage.yields(null, { imapClientStub.getMessage.yields(null, {
body: 'asdf' body: 'asdf'
}); });
devicestorageStub.removeList.yields();
devicestorageStub.storeList.yields();
emailDao.imapSync({
folder: 'INBOX',
offset: 0,
num: 2
}, function(err) {
expect(err).to.not.exist;
expect(imapClientStub.listMessages.calledOnce).to.be.true;
expect(imapClientStub.getMessage.called).to.be.false;
expect(devicestorageStub.removeList.calledOnce).to.be.true;
expect(devicestorageStub.storeList.calledOnce).to.be.true;
done();
});
});
it('should work', function(done) {
imapClientStub.listMessages.yields(null, [{
uid: 413,
subject: app.string.subject
}, {
uid: 414,
subject: app.string.subject
}]);
imapClientStub.getMessage.yields(null, {
body: 'asdf'
});
devicestorageStub.removeList.yields();
devicestorageStub.storeList.yields(); devicestorageStub.storeList.yields();
emailDao.imapSync({ emailDao.imapSync({
@ -386,6 +415,7 @@ define(function(require) {
expect(err).to.not.exist; expect(err).to.not.exist;
expect(imapClientStub.listMessages.calledOnce).to.be.true; expect(imapClientStub.listMessages.calledOnce).to.be.true;
expect(imapClientStub.getMessage.calledTwice).to.be.true; expect(imapClientStub.getMessage.calledTwice).to.be.true;
expect(devicestorageStub.removeList.calledOnce).to.be.true;
expect(devicestorageStub.storeList.calledOnce).to.be.true; expect(devicestorageStub.storeList.calledOnce).to.be.true;
done(); done();
}); });

View File

@ -71,7 +71,6 @@ define(['underscore', 'cryptoLib/util', 'js/crypto/crypto', 'js/dao/devicestorag
}); });
asyncTest("List items", 4, function() { asyncTest("List items", 4, function() {
var senderPubkeys = [devicestorageTest.generatedKeypair.publicKey]; var senderPubkeys = [devicestorageTest.generatedKeypair.publicKey];
var offset = 2, var offset = 2,
@ -94,4 +93,13 @@ define(['underscore', 'cryptoLib/util', 'js/crypto/crypto', 'js/dao/devicestorag
}); });
}); });
asyncTest("Delete List items", 1, function() {
// list encrypted items from storage
storage.removeList('email_inbox', function(err) {
ok(!err);
start();
});
});
}); });

View File

@ -21,12 +21,18 @@ define(['js/dao/lawnchair-dao'], function(jsonDao) {
}); });
}); });
asyncTest("CRUD object literal", 4, function() { asyncTest("CRUD object literal", 5, function() {
var key = 'type_asdf'; var key = 'type_1';
var data = { var data = {
name: 'testName', name: 'testName1',
type: 'testType' type: 'testType1'
};
var key2 = 'type_2';
var data2 = {
name: 'testName2',
type: 'testType2'
}; };
// create // create
@ -49,6 +55,15 @@ define(['js/dao/lawnchair-dao'], function(jsonDao) {
jsonDao.read(key, function(updated) { jsonDao.read(key, function(updated) {
equal(updated.name, newName, 'Update'); equal(updated.name, newName, 'Update');
// persist 2nd type
jsonDao.persist(key2, data2, function() {
// delete all items of 2nd type
jsonDao.removeList(key2, function() {
jsonDao.list('type', 0, null, function(newList) {
ok(newList.length === 1, 'List');
// delete // delete
jsonDao.remove(key, function() { jsonDao.remove(key, function() {
@ -59,7 +74,9 @@ define(['js/dao/lawnchair-dao'], function(jsonDao) {
start(); start();
}); });
}); });
});
});
});
}); });
}); });
}); });