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:
parent
7eb885c679
commit
267e889872
@ -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]);
|
||||||
});
|
});
|
||||||
|
@ -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;
|
||||||
});
|
});
|
@ -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);
|
||||||
});
|
});
|
||||||
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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();
|
||||||
});
|
});
|
||||||
|
@ -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();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
@ -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();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user