mirror of
https://github.com/moparisthebest/mail
synced 2024-11-22 17:02:17 -05:00
list and store only encrypted emails in local db
This commit is contained in:
parent
7eb885c679
commit
267e889872
@ -52,6 +52,7 @@ define(function(require) {
|
||||
|
||||
// development
|
||||
createDummyMails(function(emails) {
|
||||
updateStatus('Last update: ', new Date());
|
||||
$scope.emails = emails;
|
||||
$scope.select($scope.emails[0]);
|
||||
});
|
||||
|
@ -30,7 +30,6 @@ define(function(require) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
|
||||
// validate type
|
||||
if (!type) {
|
||||
callback({
|
||||
@ -41,16 +40,7 @@ define(function(require) {
|
||||
|
||||
// format items for batch storing in dao
|
||||
list.forEach(function(i) {
|
||||
// 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;
|
||||
}
|
||||
key = createKey(i, type);
|
||||
|
||||
items.push({
|
||||
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
|
||||
* @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)
|
||||
*/
|
||||
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);
|
||||
};
|
||||
|
||||
//
|
||||
// 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;
|
||||
});
|
@ -400,7 +400,8 @@ define(function(require) {
|
||||
* High level sync operation for the delta from the user's IMAP inbox
|
||||
*/
|
||||
EmailDAO.prototype.imapSync = function(options, callback) {
|
||||
var self = this;
|
||||
var self = this,
|
||||
dbType = 'email_' + options.folder;
|
||||
|
||||
// validate options
|
||||
if (!options.folder || typeof options.offset === 'undefined' || typeof options.num === 'undefined') {
|
||||
@ -411,13 +412,22 @@ define(function(require) {
|
||||
}
|
||||
|
||||
fetchList(options, function(emails) {
|
||||
// persist encrypted list in device storage
|
||||
self._devicestorage.storeList(emails, 'email_' + options.folder, function() {
|
||||
callback();
|
||||
// delete old items from db
|
||||
self._devicestorage.removeList(dbType, function(err) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
// persist encrypted list in device storage
|
||||
self._devicestorage.storeList(emails, dbType, function(err) {
|
||||
callback(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function fetchList(folder, callback) {
|
||||
var encryptedList = [];
|
||||
|
||||
// fetch imap folder's message list
|
||||
self.imapListMessages({
|
||||
folder: options.folder,
|
||||
@ -429,8 +439,15 @@ define(function(require) {
|
||||
return;
|
||||
}
|
||||
|
||||
// find encrypted messages by subject
|
||||
emails.forEach(function(i) {
|
||||
if (i.subject === str.subject) {
|
||||
encryptedList.push(i);
|
||||
}
|
||||
});
|
||||
|
||||
// fetch message bodies
|
||||
fetchBodies(emails, folder, function(messages) {
|
||||
fetchBodies(encryptedList, folder, function(messages) {
|
||||
callback(messages);
|
||||
});
|
||||
});
|
||||
@ -439,6 +456,11 @@ define(function(require) {
|
||||
function fetchBodies(messageList, folder, callback) {
|
||||
var emails = [];
|
||||
|
||||
if (messageList.length < 1) {
|
||||
callback(emails);
|
||||
return;
|
||||
}
|
||||
|
||||
var after = _.after(messageList.length, function() {
|
||||
callback(emails);
|
||||
});
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* 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';
|
||||
|
||||
var self = {},
|
||||
@ -118,6 +118,35 @@ define(['lawnchair', 'lawnchairSQL', 'lawnchairIDB'], function(Lawnchair) {
|
||||
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
|
||||
*/
|
||||
|
@ -35,8 +35,8 @@
|
||||
}
|
||||
|
||||
ul {
|
||||
padding: 0 $padding-horizontal;
|
||||
max-height: 100%;
|
||||
padding: 0 $padding-horizontal 90px $padding-horizontal;
|
||||
height: 100%;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
|
@ -367,7 +367,7 @@ define(function(require) {
|
||||
});
|
||||
|
||||
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, [{
|
||||
uid: 413,
|
||||
}, {
|
||||
@ -376,6 +376,35 @@ define(function(require) {
|
||||
imapClientStub.getMessage.yields(null, {
|
||||
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();
|
||||
|
||||
emailDao.imapSync({
|
||||
@ -386,6 +415,7 @@ define(function(require) {
|
||||
expect(err).to.not.exist;
|
||||
expect(imapClientStub.listMessages.calledOnce).to.be.true;
|
||||
expect(imapClientStub.getMessage.calledTwice).to.be.true;
|
||||
expect(devicestorageStub.removeList.calledOnce).to.be.true;
|
||||
expect(devicestorageStub.storeList.calledOnce).to.be.true;
|
||||
done();
|
||||
});
|
||||
|
@ -71,7 +71,6 @@ define(['underscore', 'cryptoLib/util', 'js/crypto/crypto', 'js/dao/devicestorag
|
||||
});
|
||||
|
||||
asyncTest("List items", 4, function() {
|
||||
|
||||
var senderPubkeys = [devicestorageTest.generatedKeypair.publicKey];
|
||||
|
||||
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();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
@ -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 = {
|
||||
name: 'testName',
|
||||
type: 'testType'
|
||||
name: 'testName1',
|
||||
type: 'testType1'
|
||||
};
|
||||
|
||||
var key2 = 'type_2';
|
||||
var data2 = {
|
||||
name: 'testName2',
|
||||
type: 'testType2'
|
||||
};
|
||||
|
||||
// create
|
||||
@ -49,17 +55,28 @@ define(['js/dao/lawnchair-dao'], function(jsonDao) {
|
||||
jsonDao.read(key, function(updated) {
|
||||
equal(updated.name, newName, 'Update');
|
||||
|
||||
// delete
|
||||
jsonDao.remove(key, function() {
|
||||
// persist 2nd type
|
||||
jsonDao.persist(key2, data2, function() {
|
||||
|
||||
// should read empty
|
||||
jsonDao.read(key, function(lastRead) {
|
||||
equal(lastRead, undefined, 'Delete');
|
||||
// delete all items of 2nd type
|
||||
jsonDao.removeList(key2, function() {
|
||||
|
||||
start();
|
||||
jsonDao.list('type', 0, null, function(newList) {
|
||||
ok(newList.length === 1, 'List');
|
||||
|
||||
// delete
|
||||
jsonDao.remove(key, function() {
|
||||
|
||||
// should read empty
|
||||
jsonDao.read(key, function(lastRead) {
|
||||
equal(lastRead, undefined, 'Delete');
|
||||
|
||||
start();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user