Skip to content

Commit

Permalink
Closes gh-4: Remove upgrade support for v0.0.1 db format
Browse files Browse the repository at this point in the history
    * app/models/ring.js (_startDepotLoad): Do first-run tasks if no depot
    data is found.
    (_loadDataHandler): Remove first-run code and other legacy stuff.
    Add or enchance comments on a few methods.

    * app/models/upgrader.js: Remove version 0 upgrader, add comments.
  • Loading branch information
Dirk Bergstrom committed Jan 2, 2010
1 parent 87bcbda commit d6b7157
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 195 deletions.
10 changes: 10 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
2010-01-01 Dirk Bergstrom <krid@otisbean.com>

* appinfo.js: Bump version for release.

Closes gh-4: Remove upgrade support for v0.0.1 db format
* app/models/ring.js (_startDepotLoad): Do first-run tasks if no depot
data is found.
(_loadDataHandler): Remove first-run code and other legacy stuff.
Add or enchance comments on a few methods.

* app/models/upgrader.js: Remove version 0 upgrader, add comments.

Closes gh-2: Can't have more than 10 categories
* app/models/ring.js (editCategory): Sort numerically instead of lexically
when finding next available index. Add logging.
Expand Down
25 changes: 12 additions & 13 deletions app/models/ring.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* @author Dirk Bergstrom
*
* Keyring for webOS - Easy password management on your phone.
* Copyright (C) 2009, Dirk Bergstrom, keyring@otisbean.com
* Copyright (C) 2009-2010, Dirk Bergstrom, keyring@otisbean.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -149,6 +149,9 @@ var Ring = Class.create ({
);
},

/**
* Create the master password (first run) or change it.
*/
newPassword: function(oldPassword, newPassword) {
Mojo.Log.info("newPassword");
if (! newPassword) {
Expand Down Expand Up @@ -238,8 +241,8 @@ var Ring = Class.create ({
* Called to start the data loading process. Kicks off the read of the
* schema version.
*
* The loading process is broken down into a number of methods, because
* of asynchronous Depot reads, and to allow the Upgrader to intervene in
* The loading process is broken down into a number of methods because
* of asynchronous Depot reads and to allow the Upgrader to intervene in
* the process as needed.
*/
initDepotReader: function(callback) {
Expand All @@ -265,12 +268,16 @@ var Ring = Class.create ({
_startDepotLoad: function(versionObj) {
var depotVersion;
if (versionObj) {
// There's data in them thar depots. This is not the first run
depotVersion = versionObj.version;
// Avoid race condition on app startup
this.firstRun = false;
} else {
// First releases didn't have a version key in Depot
depotVersion = 0;
Mojo.Log.info("This is the first run. Welcome to Keyring.");
this._salt = this.generatePassword({characters: 12, all: true});
this.prefs = Object.clone(this.DEFAULT_PREFS);
this.depotDataLoaded = true;
return this._postLoadTasks();
}
Mojo.Log.info("Current depotVersion", depotVersion);
if (depotVersion != this.SCHEMA_VERSION) {
Expand Down Expand Up @@ -314,14 +321,6 @@ var Ring = Class.create ({
this.errors.push(errmsg);
Mojo.Log.error(errmsg);
}
if (this._salt) {
this.firstRun = false;
Mojo.Log.info("checkData:", this._checkData, "salt:", this._salt);
} else {
// First run or factory reset, generate salt
this._salt = this.generatePassword({characters: 12, all: true});
Mojo.Log.info("Generated new salt: ", this._salt);
}
if (! this.prefs) {
// Copy default prefs
this.prefs = Object.clone(this.DEFAULT_PREFS);
Expand Down
210 changes: 28 additions & 182 deletions app/models/upgrader.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* Violates encapsulation in horrible ways.
*
* Keyring for webOS - Easy password management on your phone.
* Copyright (C) 2009, Dirk Bergstrom, keyring@otisbean.com
* Copyright (C) 2009-2010, Dirk Bergstrom, keyring@otisbean.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand All @@ -22,212 +22,58 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

var _V0 = Class.create ({

DEPOT_ITEMS_KEY: "items",

DEPOT_CRYPT_KEY: "crypt-info",

DEPOT_PREFS_KEY: "prefs",
/**
* Schema version #3 added categories.
*/
var _V2 = Class.create ({

// Callbacks used during initialization
_itemsLoadedCallback: function() {},
_cryptInfoLoadedCallback: function() {},
_prefsLoadedCallback: function() {},

db: null,
prefs: null,
_salt: '',
_checkData: '',
ring: null,
depot: null,

initialize: function(ring) {
Mojo.Log.info("Initializing V0 upgrader");
Mojo.Log.info("Initializing V2 upgrader");
this.ring = ring;
this.depot = ring.depot;
},

upgrade: function() {
this.loadDepotData(this.processData.bind(this));
/* Tell the ring to load its data, but insert our processData()
* method in the pipeline. */
this.ring._loadRingData(this.processData.bind(this));
},

/*
* This is the method that does the actual upgrade work, by translating
* old-style data to new style.
* It will need to be modified each time a new schema is created.
* It will (probably) need to be modified each time a new schema is created.
*
* IMPORTANT: Because version 1/2 had no version key in the depot, we'll
* get here on the first fun of any version that has the ability to
* upgrade from those early versions.
* In this case, we're just pumping all the items thru ring._upgradeItem(),
* which will add the new category attribute.
*/
processData: function(timedOut) {
Mojo.Log.info("V0 upgrader processing data; timedOut='%s'", timedOut);
if (this.db || this._checkData || this.prefs) {
Mojo.Log.info("Found actual version 1/2 data");
try {
if (this.prefs) {
// Add in new "import" & "export" prefs
this.prefs.import_ = Object.clone(this.ring.DEFAULT_PREFS.import_);
this.prefs.export_ = Object.clone(this.ring.DEFAULT_PREFS.export_);
} else {
this.prefs = Object.clone(this.ring.DEFAULT_PREFS);
}
var dataObj = {
db: this.db,
crypt: {
salt: this._salt,
checkData: this._checkData
},
prefs: this.prefs
};
this.ring._loadDataHandler(dataObj);
this.ring.saveData(true);

// Add a helper function to handle the old checkData format
this.ring._upgradeCheckData = function(tmpKey) {
Mojo.Log.info("Upgrading checkData");
if (this.decrypt(this._checkData, tmpKey) == 'elderberries') {
this._key = tmpKey;
this._checkData = this.encrypt(tmpKey);
}
}.bind(this.ring);

// Finally, toss out the old data
this.deleteOldData();
}
catch(e) {
var errmsg = "Severe Upgrader error converting version 1/2 data: " +
e.name + ": " + e.message;
this.ring.errors.push(errmsg);
Mojo.Log.error(errmsg);
}
} else {
Mojo.Log.info("Upgrader found no version 1/2 data, this is the first run");
this.ring._salt = this.ring.generatePassword({characters: 12, all: true});
this.ring.prefs = Object.clone(this.ring.DEFAULT_PREFS);
this.ring.depotDataLoaded = true;
this.ring._dataLoadedCallback();
}
},

// Get rid of the old data
deleteOldData: function() {
Mojo.Log.info("VO upgrader deleting old depot data");
[this.DEPOT_ITEMS_KEY, this.DEPOT_CRYPT_KEY, this.DEPOT_PREFS_KEY].each(
function(key) {
Mojo.Log.info("VO upgrader deleting depot key", key);
/* discard is not implemented as of Mojo 1.1, even though
* it's listed in Palm's API docs. Jerks. */
try {
this.depot.discard(key,
function() {
Mojo.Log.info("VO upgrader discarded old depot key '%s'", key);
},
function(error) {
var errmsg = "V0 upgrader failed to overwrite key '" +
key + "': " + error;
this.ring.errors.push(errmsg);
Mojo.Log.error(errmsg);
}
);
}
catch(e) {
// Rrrgh, no discard. Overwrite with empty object.
this.depot.add(key, {},
function() {
Mojo.Log.info("VO upgrader overwrote old depot key '%s'", key);
},
function(error) {
var errmsg = "V0 upgrader failed to overwrite key '" +
key + "': " + error;
this.ring.errors.push(errmsg);
Mojo.Log.error(errmsg);
}
);
}
}, this);
},

// Read data from the old version's depot
loadDepotData: function(callback) {
/* Set up a synchronizer that will call the supplied callback when
* all the loaders have finished. */
var synchronizer = new Mojo.Function.Synchronize({
syncCallback: callback});
this._itemsLoadedCallback = synchronizer.wrap(function() {});
this._cryptInfoLoadedCallback = synchronizer.wrap(function() {});
this._prefsLoadedCallback = synchronizer.wrap(function() {});

this.depot.get(this.DEPOT_ITEMS_KEY,
this.loadItems.bind(this),
function(error) {
this._itemsLoadedCallback();
var errmsg = "V0 upgrader Could not fetch items: " + error;
this.ring.errors.push(errmsg);
Mojo.Log.error(errmsg);
}
);
this.depot.get(this.DEPOT_CRYPT_KEY,
this.loadCryptInfo.bind(this),
function(error) {
this._cryptInfoLoadedCallback();
var errmsg = "V0 upgrader Could not fetch crypt-info: " + error;
this.ring.errors.push(errmsg);
Mojo.Log.error(errmsg);
}
);
this.depot.get(this.DEPOT_PREFS_KEY,
this.loadPrefs.bind(this),
function(error) {
var errmsg = "V0 upgrader Could not fetch prefs: " + error;
this.ring.errors.push(errmsg);
Mojo.Log.error(errmsg);
this._prefsLoadedCallback();
}
);
},

loadItems: function(obj) {
// Read hash of items from the depot
if (obj) {
this.db = obj;
Mojo.Log.info("V0 upgrader Loaded item db");
}
this._itemsLoadedCallback();
},

loadCryptInfo: function(obj) {
// Read hash of crypto info from the depot
if (obj) {
Mojo.Log.info("V0 upgrader Loaded crypt info");
this._salt = obj.salt;
this._checkData = obj.checkData;
}
this._cryptInfoLoadedCallback();
},

loadPrefs: function(obj) {
// Read hash of prefs info from the depot
if (obj) {
this.prefs = obj;
Mojo.Log.info("V0 upgrader Loaded prefs object");
} else {
Mojo.Log.info("V0 upgrader found no prefs object");
}
this._prefsLoadedCallback();
Mojo.Log.info("V2 upgrader processing data");

Object.values(this.ring.db).each(function(item) {
this.ring.db[item.title] = this.ring._upgradeItem(item);
}, this);

Mojo.Log.info("V2 upgrader saving processed data");
// Need to pass 'true' to tell saveData to write out the new schema_version.
this.ring.saveData(true);
this.ring._postLoadTasks();
}
});

/**
* An Upgrader upgrades from the given version to current.
*/
var Upgrader = Class.create ({

worker: null,

initialize: function(version, ring) {
Mojo.Log.info("Initializing upgrader for version", version);
if (version === 0) {
this.worker = new _V0(ring);
}
if (version === 2) {
this.worker = new _V2(ring);
}
},

upgrade: function() {
Expand Down

0 comments on commit d6b7157

Please sign in to comment.