Diffstat (limited to 'frontend/gamma/js/Clipperz/PM/DataModel') (more/less context) (ignore whitespace changes)
14 files changed, 165 insertions, 262 deletions
diff --git a/frontend/gamma/js/Clipperz/PM/DataModel/DirectLogin.js b/frontend/gamma/js/Clipperz/PM/DataModel/DirectLogin.js index 8f8696d..507ee31 100644 --- a/frontend/gamma/js/Clipperz/PM/DataModel/DirectLogin.js +++ b/frontend/gamma/js/Clipperz/PM/DataModel/DirectLogin.js @@ -1,1073 +1,1063 @@ /* -Copyright 2008-2011 Clipperz Srl +Copyright 2008-2013 Clipperz Srl -This file is part of Clipperz Community Edition. -Clipperz Community Edition is an online password manager. +This file is part of Clipperz, the online password manager. For further information about its features and functionalities please refer to http://www.clipperz.com. -* Clipperz Community Edition is free software: you can redistribute - it and/or modify it under the terms of the GNU Affero General Public - License as published by the Free Software Foundation, either version - 3 of the License, or (at your option) any later version. +* Clipperz is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. -* Clipperz Community Edition is distributed in the hope that it will - be useful, but WITHOUT ANY WARRANTY; without even the implied - warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* Clipperz is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. * You should have received a copy of the GNU Affero General Public - License along with Clipperz Community Edition. If not, see - <http://www.gnu.org/licenses/>. + License along with Clipperz. If not, see http://www.gnu.org/licenses/. */ Clipperz.Base.module('Clipperz.PM.DataModel'); Clipperz.PM.DataModel.DirectLogin = function(args) { args = args || {}; Clipperz.PM.DataModel.DirectLogin.superclass.constructor.apply(this, arguments); this._reference = args.reference || Clipperz.PM.Crypto.randomKey(); this._record = args.record || Clipperz.Base.exception.raise('MandatoryParameter'); this._retrieveIndexDataFunction = args.retrieveIndexDataFunction || this.record().retrieveDirectLoginIndexDataFunction() || Clipperz.Base.exception.raise('MandatoryParameter'); this._setIndexDataFunction = args.setIndexDataFunction || this.record().setDirectLoginIndexDataFunction() || Clipperz.Base.exception.raise('MandatoryParameter'); this._removeIndexDataFunction = args.removeIndexDataFunction || this.record().removeDirectLoginIndexDataFunction() || Clipperz.Base.exception.raise('MandatoryParameter'); this._inputs = null; this._bindings = null; this._formValues = null; // this._inputsDeferredLock = new MochiKit.Async.DeferredLock(); // this._bindingsDeferredLock = new MochiKit.Async.DeferredLock(); // this._formValuesDeferredLock = new MochiKit.Async.DeferredLock(); this._transientState = null; this._isBrandNew = MochiKit.Base.isUndefinedOrNull(args.reference); this.record().addDirectLogin(this); return this; } Clipperz.Base.extend(Clipperz.PM.DataModel.DirectLogin, Object, { 'toString': function() { return "DirectLogin (" + this.reference() + ")"; }, //========================================================================= 'reference': function () { return this._reference; }, //------------------------------------------------------------------------- 'record': function () { return this._record; }, //========================================================================= 'isBrandNew': function () { return this._isBrandNew; }, //========================================================================= 'removeIndexDataFunction': function () { return this._removeIndexDataFunction; }, 'remove': function () { return Clipperz.Async.callbacks("DirectLogin.remove", [ MochiKit.Base.partial(this.removeIndexDataFunction(), this.reference()), MochiKit.Base.method(this.record(), 'removeDirectLogin', this) ], {trace:false}); }, //========================================================================= /* 'inputsDeferredLock': function () { return this._inputsDeferredLock; }, 'bindingsDeferredLock': function () { return this._bindingsDeferredLock; }, 'formValuesDeferredLock': function () { return this._formValuesDeferredLock; }, */ //========================================================================= 'label': function () { return this.getIndexDataForKey('label'); }, 'setLabelKeepingBackwardCompatibilityWithBeta': function (aValue) { return Clipperz.Async.callbacks("DirectLogin.setLabelKeepingBackwardCompatibilityWithBeta", [ MochiKit.Base.method(this, 'setIndexDataForKey', 'label', aValue), MochiKit.Base.method(this, 'setValue', 'label', aValue) ], {trace:false}); }, 'setLabel': function (aValue) { return this.setLabelKeepingBackwardCompatibilityWithBeta(aValue); // return this.setIndexDataForKey('label', aValue); }, //========================================================================= 'favicon': function () { return this.getIndexDataForKey('favicon'); }, 'setFavicon': function (aValue) { return this.setIndexDataForKey('favicon', aValue); }, 'faviconUrlWithBookmarkletConfiguration': function (aBookmarkletConfiguration) { var result; if (! MochiKit.Base.isUndefinedOrNull(aBookmarkletConfiguration['page']['favicon'])) { result = aBookmarkletConfiguration['page']['favicon']; } else if (! MochiKit.Base.isUndefinedOrNull(aBookmarkletConfiguration['form']['attributes']['action'])) { var actionUrl; var hostname; actionUrl = aBookmarkletConfiguration['form']['attributes']['action']; hostname = actionUrl.replace(/^https?:\/\/([^\/]*)\/.*/, '$1'); result = "http://" + hostname + "/favicon.ico"; } else { result = null; } return result; }, //------------------------------------------------------------------------- /* 'faviconData': function () { var regexp = new RegExp('^data\:\/\/.*', 'i'); return Clipperz.Async.callbacks("DirectLogin.favicon", [ MochiKit.Base.method(this, 'getIndexDataForKey', 'favicon'), MochiKit.Base.method(regexp, 'test'), Clipperz.Async.deferredIf("is data URL", [ MochiKit.Base.method(this, 'getIndexDataForKey', 'favicon') ], [ MochiKit.Base.method(this, 'transientState'), MochiKit.Base.itemgetter('faviconData'), Clipperz.Async.deferredIf('has a chaced value for the favicon data', [ MochiKit.Base.operator.identity ], [ MochiKit.Base.method(this, 'getIndexDataForKey', 'favicon'), MochiKit.Base.method(this, 'loadFaviconDataFromURL') ]) ]) ], {trace:false}); }, //------------------------------------------------------------------------- 'loadFaviconDataFromURL': function (anURL) { var deferredResult; var image; deferredResult = new Clipperz.Async.Deferred("DirectLogin.loadFaviconDataFromURL", {trace:false}); deferredResult.addCallback(function (anEvent) { var image = anEvent.src(); var canvas = document.createElement("canvas"); var result; canvas.width = image.width; canvas.height = image.height; var ctx = canvas.getContext("2d"); ctx.drawImage(image, 0, 0); result = canvas.toDataURL(/*"image/png"* /); return result; }); deferredResult.addErrback(MochiKit.Async.succeed, Clipperz.PM.Strings.getValue('defaultFaviconUrl')); deferredResult.addBoth(MochiKit.Base.bind(function (aDataUrl) { this.transientState()['faviconData'] = aDataUrl; return aDataUrl; }, this)); image = new Image(); MochiKit.Signal.connect(image, 'onload', MochiKit.Base.method(deferredResult, 'callback')); MochiKit.Signal.connect(image, 'onerror', MochiKit.Base.method(deferredResult, 'errback')); MochiKit.Signal.connect(image, 'onabort', MochiKit.Base.method(deferredResult, 'errback')); image.src = anURL; return deferredResult; }, */ //========================================================================= 'type': function () { return this.getValue('formData.attributes.type') }, //========================================================================= 'serializedData': function () { return Clipperz.Async.collectResults("DirectLogin.serializedData", { 'bookmarkletVersion': MochiKit.Base.method(this, 'getValue', 'bookmarkletVersion'), 'formData': MochiKit.Base.method(this, 'getValue', 'formData'), 'formValues': MochiKit.Base.method(this, 'getValue', 'formValues'), 'bindingData': [ MochiKit.Base.method(this, 'bindings'), function (someBindings) { var result; var bindingKey; result = {} for (bindingKey in someBindings) { result[bindingKey] = someBindings[bindingKey].serializedData(); } return result; } ] }, {trace:false})() }, //========================================================================= /* 'fixFormDataFromBookmarkletVersion_0_1': function(aValue) { //{"type":"radio", "name":"action", "value":"new-user", "checked":false }, { "type":"radio", "name":"action", "value":"sign-in", "checked":true } // || // \ / // \/ //{"name":"dominio", "type":"radio", "options":[{"value":"@alice.it", "checked":true}, {"value":"@tin.it", "checked":false}, {"value":"@virgilio.it", "checked":false}, {"value":"@tim.it", "checked":false}]} var result; var inputs; var updatedInputs; var radios; result = aValue; inputs = aValue['inputs']; updatedInputs = MochiKit.Base.filter(function(anInput) { var result; var type; type = anInput['type'] || 'text'; result = type.toLowerCase() != 'radio'; return result; }, inputs); radios = MochiKit.Base.filter(function(anInput) { var result; var type; type = anInput['type'] || 'text'; result = type.toLowerCase() == 'radio'; return result; }, inputs); if (radios.length > 0) { var updatedRadios; updatedRadios = {}; MochiKit.Iter.forEach(radios, MochiKit.Base.bind(function(aRadio) { var radioConfiguration; radioConfiguration = updatedRadios[aRadio['name']]; if (radioConfiguration == null) { radioConfiguration = {type:'radio', name:aRadio['name'], options:[]}; updatedRadios[aRadio['name']] = radioConfiguration; } // TODO: remove the value: field and replace it with element.dom.value = <some value> radioConfiguration.options.push({value:aRadio['value'], checked:aRadio['checked']}); // TODO: shoud remove the 'formValues' call, as it is now deferred // if ((aRadio['checked'] == true) && (this.formValues()[aRadio['name']] == null)) { // this.formValues()[aRadio['name']] = aRadio['value']; // } }, this)) updatedInputs = MochiKit.Base.concat(updatedInputs, MochiKit.Base.values(updatedRadios)); } delete result.inputs; result.inputs = updatedInputs; return result; }, '_fixConfiguration': function (aConfiguration) { var fixedConfiguration; // var inputs; // var bindings; // var i,c; fixedConfiguration = Clipperz.Base.deepClone(aConfiguration); -//console.log("PROCESS CONFIGURATION", aConfiguration); +//Clipperz.log("PROCESS CONFIGURATION", aConfiguration); switch (aConfiguration['bookmarkletVersion']) { case '0.1': fixedConfiguration['formData'] = this.fixFormDataFromBookmarkletVersion_0_1(aConfiguration['formData']); break; case '0.2': fixedConfiguration['formData'] = aConfiguration['formData']; break; } / * aConfiguration['_inputs'] = []; c = formData['inputs'].length; for (i=0; i<c; i++) { aConfiguration['_inputs'].push(new Clipperz.PM.DataModel.DirectLoginInput(formData['inputs'][i])); } * / / * aConfiguration['_bindings'] = {}; if (aConfiguration['legacyBindingData'] == null) { if (aConfiguration['bindingData'] != null) { var bindingKey; for (bindingKey in aConfiguration['bindingData']) { var newBinding; newBinding = new Clipperz.PM.DataModel.DirectLoginBinding(bindingKey, {fieldKey:aConfiguration['bindingData'][bindingKey]}); aConfiguration['_bindings'][newBinding.key()] = newBinding; } } else { var editableFields; editableFields = MochiKit.Base.filter(function(aField) { var result; var type; type = aField['type'].toLowerCase(); result = ((type != 'hidden') && (type != 'submit') && (type != 'checkbox') && (type != 'radio') && (type != 'select')); return result; }, aConfiguration['_inputs']); MochiKit.Iter.forEach(editableFields, MochiKit.Base.bind(function(anEditableField) { var newBinding; newBinding = new Clipperz.PM.DataModel.DirectLoginBinding(anEditableField['name']); aConfiguration['_bindings'][newBinding.key()] = newBinding; }, this)); } } else { var bindingKey; for (bindingKey in aConfiguration['legacyBindingData']) { var newBinding; newBinding = new Clipperz.PM.DataModel.DirectLoginBinding(bindingKey, {fieldName:aConfiguration['legacyBindingData'][bindingKey]}); aConfiguration['_bindings'][newBinding.key()] = newBinding; } } * / return fixedConfiguration; }, //------------------------------------------------------------------------- 'getObjectDataStore': function () { var deferredResult; deferredResult = new Clipperz.Async.Deferred("DirectLogin.getObjectDataStore", {trace:false}); deferredResult.acquireLock(this.objectDataStoreDeferredLock()); deferredResult.addCallback(MochiKit.Base.bind(function () { var innerDeferredResult; if (this._objectDataStore == null) { this._objectDataStore = new Clipperz.KeyValueObjectStore(); innerDeferredResult = new Clipperz.Async.Deferred("DirectLogin.getObjectDataStore <inner deferred>", {trace:false}); // innerDeferredResult.addMethod(this.record(), 'getValue', 'directLogins' + '.' + this.reference()); innerDeferredResult.addMethod(this, 'getValue', ''), innerDeferredResult.addMethod(this, 'setOriginalState'); innerDeferredResult.addMethod(this, '_fixConfiguration'); innerDeferredResult.addMethod(this._objectDataStore, 'initWithValues'); // innerDeferredResult.addMethod(this._objectDataStore, 'setValues'); innerDeferredResult.callback(); } else { innerDeferredResult = MochiKit.Async.succeed(this._objectDataStore); } return innerDeferredResult; }, this)); deferredResult.releaseLock(this.objectDataStoreDeferredLock()); deferredResult.callback(); return deferredResult; }, //------------------------------------------------------------------------- 'hasInitiatedObjectDataStore': function () { return (this._objectDataStore != null); }, //------------------------------------------------------------------------- 'resetObjectDataStore': function () { this._objectDataStore.removeAllData(); this._objectDataStore = null; }, */ //========================================================================= 'bookmarkletConfiguration': function () { return Clipperz.Async.callbacks("DirectLogin.bookmarkletConfiguration", [ Clipperz.Async.collectResults("DirectLogin.bookmarkletConfiguration <inner results>", { 'label': MochiKit.Base.method(this, 'label'), 'configuration': MochiKit.Base.method(this, 'getValue', '') }, {trace:false}), function (someValues) { var result; if (someValues['configuration'] != null) { var configuration; configuration = { 'page': { 'title': someValues['label'] // 'favicon' // 'url' }, 'form': someValues['configuration']['formData'], 'version': someValues['configuration']['bookmarkletVersion'] } result = Clipperz.Base.formatJSON(configuration); } else { result = ''; } return result; } ], {trace:false}); }, //------------------------------------------------------------------------- 'setBookmarkletConfiguration': function (aValue) { var bookmarkletConfiguration; bookmarkletConfiguration = Clipperz.PM.DataModel.DirectLogin.checkBookmarkletConfiguration(aValue); -//console.log("BOOKMARKLET CONFIGURATION", bookmarkletConfiguration); + return Clipperz.Async.callbacks("DirectLogin.setBookmarkletConfiguration", [ MochiKit.Base.method(this, 'setValue', 'formData', bookmarkletConfiguration['form']), -//function (aValue) { console.log("SET VALUE - formData", aValue); return aValue; }, MochiKit.Base.method(this, 'setValue', 'bookmarkletVersion', bookmarkletConfiguration['version']), MochiKit.Base.method(this, 'favicon'), Clipperz.Async.deferredIf("the favicon is not set", [ ], [ MochiKit.Base.method(this, 'faviconUrlWithBookmarkletConfiguration', bookmarkletConfiguration), MochiKit.Base.method(this, 'setFavicon') ]), MochiKit.Base.method(this, 'updateInputsAfterChangingBookmarkletConfiguration'), MochiKit.Base.method(this, 'updateFormValuesAfterChangingBookmarkletConfiguration'), MochiKit.Base.method(this, 'updateBindingsAfterChangingBookmarkletConfiguration'), MochiKit.Base.noop ], {trace:false}); }, //========================================================================= 'formAttributes': function () { return this.getValue('formData.attributes'); }, //========================================================================= 'inputs': function () { return Clipperz.Async.callbacks("DirectLogin.inputs", [ Clipperz.Async.deferredIf("this._inputs is defined", [ ], [ MochiKit.Base.method(this, 'updateInputsAfterChangingBookmarkletConfiguration') ]) ], {trace:false}, this._inputs); }, 'setInputWithFormDataConfiguration': function (aFormDataConfiguration) { this._inputs = {}; if (aFormDataConfiguration != null) { MochiKit.Iter.forEach(aFormDataConfiguration['inputs'], MochiKit.Base.bind(function (anInputData) { var newInput; newInput = new Clipperz.PM.DataModel.DirectLoginInput(anInputData); this._inputs[newInput.name()] = newInput; }, this)); } return this._inputs; }, 'updateInputsAfterChangingBookmarkletConfiguration': function () { return Clipperz.Async.callbacks("DirectLogin.updateInputsAfterChangingBookmarkletConfiguration", [ -// MochiKit.Base.method(this, 'getValue', ''), -//function (aValue) { console.log("VALUE", aValue); return aValue }, MochiKit.Base.method(this, 'getValue', 'formData'), -//function (aValue) { console.log("FORM DATA", aValue); return aValue }, MochiKit.Base.method(this, 'setInputWithFormDataConfiguration') ], {trace:false}); }, //========================================================================= 'inputValues': function () { return Clipperz.Async.callbacks("DirectLogin.inputValues", [ MochiKit.Base.method(this, 'inputs'), MochiKit.Base.values, -//function (aValue) { console.log("INPUTS", aValue); return aValue; }, MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.partial(MochiKit.Base.method(this, 'inputValue'))), Clipperz.Async.collectAll, Clipperz.Base.mergeItems ], {trace:false}); }, 'inputValue': function (anInput) { var deferredResult; deferredResult = new Clipperz.Async.Deferred("DirectLogin.inputValue", {trace:false}); if (anInput.needsFormValue()) { deferredResult.addMethod(this, 'formValues'); deferredResult.addCallback(MochiKit.Base.itemgetter(anInput.name())); deferredResult.addMethodcaller('value'); } else if (anInput.needsBinding()) { deferredResult.addMethod(this, 'bindings'); deferredResult.addCallback(MochiKit.Base.itemgetter(anInput.name())); deferredResult.addMethodcaller('field'); deferredResult.addMethodcaller('value'); } else { deferredResult.addCallback(MochiKit.Async.succeed, anInput.value()); } deferredResult.addCallback(function (anActualValue) { return [anInput.name(), anActualValue]; }); deferredResult.callback(); return deferredResult; }, //========================================================================= 'bindings': function () { return Clipperz.Async.callbacks("DirectLogin.bindings", [ Clipperz.Async.deferredIf("this._bindings is defined", [ ], [ MochiKit.Base.method(this, 'updateBindingsAfterChangingBookmarkletConfiguration'), MochiKit.Base.bind(function () { return this._bindings;}, this) ]) ], {trace:false}, this._bindings); }, 'bindFormFieldWithLabelToRecordFieldWithLabel': function (aFormFieldLabel, aRecordFieldLabel) { return Clipperz.Async.callbacks("DirectLogin.bindFormFieldWithLabelToCardFieldWithLabel", [ Clipperz.Async.collectResults("DirectLogin.bindFormFieldWithLabelToCardFieldWithLabel - collect results", { 'binding': [ MochiKit.Base.method(this, 'bindings'), MochiKit.Base.itemgetter(aFormFieldLabel) ], 'field': [ MochiKit.Base.method(this.record(), 'fieldWithLabel', aRecordFieldLabel) ] }), function (someValues) { someValues['binding'].setField(someValues['field']) } ], {trace:false}); }, //------------------------------------------------------------------------- /* 'bindingValues': function () { return Clipperz.Async.callbacks("DirectLogin.bindingValues", [ Clipperz.Async.collectResults("DirectLogin.bindingValues [collectResults]", { 'fieldValues': [ MochiKit.Base.method(this, 'record'), MochiKit.Base.methodcaller('getFieldsValues') ], 'bindings': MochiKit.Base.method(this, 'bindings') }, {trace:false}), function (someData) { var result; var bindingKey; result = {}; for (bindingKey in someData['bindings']) { result[bindingKey] = someData['fieldValues'][someData['bindings'][bindingKey].fieldKey()]['value']; } return result; } ], {trace:false}); }, */ //------------------------------------------------------------------------- 'updateBindingsAfterChangingBookmarkletConfiguration': function () { return Clipperz.Async.callbacks("DirectLogin.updateBindingsAfterChangingBookmarkletConfiguration", [ Clipperz.Async.collectResults("DirectLogin.updateBindingsAfterChangingBookmarkletConfiguration<collect results>", { 'currentValues': MochiKit.Base.method(this, 'getValue', ''), 'originalValues': MochiKit.Base.method(this, 'originalConfiguration'), 'inputs': MochiKit.Base.method(this, 'inputs') }, {trace:false}), MochiKit.Base.bind(function (someValues) { var availableBindingValues; var inputRequiringBindingValues; var newBindingValues; if (MochiKit.Base.isUndefinedOrNull(someValues['originalValues']) || MochiKit.Base.isUndefinedOrNull(someValues['originalValues']['bindingData'])) { availableBindingValues = {}; } else { availableBindingValues = Clipperz.Base.deepClone(someValues['originalValues']['bindingData']) } if (someValues['currentValues'] != null) { MochiKit.Base.update(availableBindingValues, someValues['currentValues']['bindingData']); } this._bindings = {}; newBindingValues = {} MochiKit.Iter.forEach(MochiKit.Base.filter(MochiKit.Base.methodcaller('needsBinding'), MochiKit.Base.values(someValues['inputs'])), MochiKit.Base.bind(function (anInput) { var newBinding; newBindingValues[anInput.name()] = availableBindingValues[anInput.name()]; newBinding = new Clipperz.PM.DataModel.DirectLoginBinding(this, { 'key': anInput.name(), 'field': availableBindingValues[anInput.name()] }); this._bindings[anInput.name()] = newBinding; }, this)) -//console.log("THIS._BINDINGS", this._bindings); return newBindingValues; /* this._bindings = {}; -//console.log("CONFIGURATION", aConfiguration); if (someValues['currentValues'] != null) { if (someValues['currentValues']['bindingData'] != null) { var bindingKey; -//console.log("BINDING DATA", someValues['currentValues']['bindingData']); for (bindingKey in someValues['currentValues']['bindingData']) { var newBinding; newBinding = new Clipperz.PM.DataModel.DirectLoginBinding(this, { 'key': bindingKey, 'field': someValues['currentValues']['bindingData'][bindingKey] }); this._bindings[newBinding.key()] = newBinding; } } else if (someValues['currentValues']['legacyBindingData'] == null) { var bindingKey; for (bindingKey in someValues['currentValues']['legacyBindingData']) { var newBinding; newBinding = new Clipperz.PM.DataModel.DirectLoginBinding(this, { 'key': bindingKey, 'field': someValues['currentValues']['legacyBindingData'][bindingKey] }); this._bindings[newBinding.key()] = newBinding; } } else { WTF = TODO; } } return this._bindings; */ }, this), MochiKit.Base.method(this, 'setValue', 'bindingData') ], {trace:false}); }, //========================================================================= 'formValues': function () { return Clipperz.Async.callbacks("DirectLogin.formValues", [ Clipperz.Async.deferredIf("this._formValues is defined", [ ], [ MochiKit.Base.method(this, 'updateFormValuesAfterChangingBookmarkletConfiguration'), MochiKit.Base.bind(function () { return this._formValues;}, this) ]) ], {trace:false}, this._formValues); }, //------------------------------------------------------------------------- 'updateFormValuesAfterChangingBookmarkletConfiguration': function () { return Clipperz.Async.callbacks("DirectLogin.updateFormValuesAfterChangingBookmarkletConfiguration", [ Clipperz.Async.collectResults("DirectLogin.updateFormValuesAfterChangingBookmarkletConfiguration <collect results>", { 'currentValues': MochiKit.Base.method(this, 'getValue', ''), 'originalValues': MochiKit.Base.method(this, 'originalConfiguration'), 'inputs': MochiKit.Base.method(this, 'inputs') }, {trace:false}), MochiKit.Base.bind(function (someValues) { var availableFormValues; var inputRequiringFormValues; var newFormValues; if (MochiKit.Base.isUndefinedOrNull(someValues['originalValues']) || MochiKit.Base.isUndefinedOrNull(someValues['originalValues']['formValues'])) { availableFormValues = {}; } else { availableFormValues = Clipperz.Base.deepClone(someValues['originalValues']['formValues']) } MochiKit.Base.update(availableFormValues, someValues['currentValues']['formValues']); this._formValues = {}; newFormValues = {}; MochiKit.Iter.forEach(MochiKit.Base.filter(MochiKit.Base.methodcaller('needsFormValue'), MochiKit.Base.values(someValues['inputs'])), MochiKit.Base.bind(function (anInput) { var newFormValue; var fieldOptions; fieldOptions = { 'type': anInput.type(), 'options': anInput.options() }; newFormValues[anInput.name()] = availableFormValues[anInput.name()] newFormValue = new Clipperz.PM.DataModel.DirectLoginFormValue(this, { 'key': anInput.name(), 'fieldOptions': fieldOptions, 'value': availableFormValues[anInput.name()] }); this._formValues[anInput.name()] = newFormValue; }, this)) return newFormValues; }, this), MochiKit.Base.method(this, 'setValue', 'formValues') ], {trace:false}); }, //========================================================================= 'retrieveIndexDataFunction': function () { return this._retrieveIndexDataFunction; }, 'getIndexDataForKey': function (aKey) { return Clipperz.Async.callbacks("DirectLogin.getIndexDataForKey", [ MochiKit.Base.partial(this.retrieveIndexDataFunction(), this.reference()), Clipperz.Async.deferredIf("DirectLogin.getIndexDataForKey - index data not null", [ MochiKit.Base.itemgetter(aKey) ],[ MochiKit.Async.succeed ]) ], {trace:false}); }, //------------------------------------------------------------------------- 'setIndexDataForKey': function (aKey, aValue) { return Clipperz.Async.callbacks("DirectLogin.setValueForKey", [ MochiKit.Base.method(this, 'getIndexDataForKey', aKey), MochiKit.Base.bind(function (anActualValue) { var transientStateKey; transientStateKey = 'original_' + aKey; if (MochiKit.Base.isUndefinedOrNull(this.transientState()[transientStateKey])) { if (anActualValue != aValue) { this.transientState()[transientStateKey] = anActualValue; } } else if (this.transientState()[transientStateKey] == aValue) { this.transientState()[transientStateKey] = null; } }, this), MochiKit.Base.partial(this._setIndexDataFunction, this.reference(), aKey, aValue) ], {trace:false}) }, //------------------------------------------------------------------------- /* 'setValueForKey': function (aKey, aValue) { return Clipperz.Async.callbacks("DirectLogin.setValueForKey", [ MochiKit.Base.method(this, 'getIndexDataForKey', aKey), MochiKit.Base.bind(function (anActualValue) { var transientStateKey; transientStateKey = 'original_' + aKey; if (MochiKit.Base.isUndefinedOrNull(this.transientState()[transientStateKey])) { if (anActualValue != aValue) { this.transientState()[transientStateKey] = anActualValue; } } else if (this.transientState()[transientStateKey] == aValue) { this.transientState()[transientStateKey] = null; } }, this), MochiKit.Base.method(this, 'setIndexDataForKey', aKey, aValue) ], {trace:false}) }, */ //========================================================================= /* 'storedConfiguration': function () { return this.record().getValue('directLogins' + '.' + this.reference()); }, // 'setStoredConfiguration': function (aValue) { // return this.record().setValue('directLogins' + '.' + this.reference(), aValue); // }, */ //========================================================================= 'hasPendingChanges': function () { var result; var deferredResult; result = false; result = result || this.isBrandNew(); result = result || (! MochiKit.Base.isUndefinedOrNull(this.transientState()['original_label'])); result = result || (! MochiKit.Base.isUndefinedOrNull(this.transientState()['original_favicon'])); if ((result == false) && (this.originalConfiguration() != null)) { deferredResult = Clipperz.Async.callbacks("DirectLogin.hasPendingChanges", [ MochiKit.Base.method(this, 'serializedData'), MochiKit.Base.bind(function (aCurrentConfiguration) { var originalConfiguration; var currentConfiguration; var result; originalConfiguration = this.originalConfiguration(); currentConfiguration = aCurrentConfiguration; result = false; result = result || (MochiKit.Base.compare(originalConfiguration['bookmarkletVersion'], currentConfiguration['bookmarkletVersion']) != 0); result = result || (MochiKit.Base.compare(originalConfiguration['formData'], currentConfiguration['formData']) != 0); result = result || (MochiKit.Base.compare(originalConfiguration['formValues'], currentConfiguration['formValues']) != 0); result = result || (MochiKit.Base.compare(originalConfiguration['bindingData'], currentConfiguration['bindingData']) != 0); return result; }, this) ], {trace:false}); } else { deferredResult = MochiKit.Async.succeed(result); } return deferredResult; }, //------------------------------------------------------------------------- 'revertChanges': function () { var deferredResult; if (this.transientState()['original_label'] != null) { this.setLabel(this.transientState()['original_label']); } if (this.transientState()['original_favicon'] != null) { this.setFavicon(this.transientState()['original_favicon']); } if (this.originalConfiguration() != null) { deferredResult = this.setValue('', this.originalConfiguration()); } else { deferredResult = MochiKit.Async.succeed(); } this._inputs = null; this._bindings = null; this._formValues = null; this.resetTransientState(false); /* if (this.hasInitiatedObjectDataStore()) { deferredResult = Clipperz.Async.callbacks("DirectLogin.revertChanges", [ // MochiKit.Base.method(this.record(), 'setValue', 'directLogins' + '.' + this.reference(), this.originalState()), MochiKit.Base.method(this, 'setValue', '', this.originalState()), MochiKit.Base.method(this, 'resetObjectDataStore') ], {trace:false}) } else { deferredResult = MochiKit.Async.succeed(); } */ return deferredResult; }, //========================================================================= 'transientState': function () { if (this._transientState == null) { this._transientState = {} } return this._transientState; }, 'resetTransientState': function (isCommitting) { this._transientState = null; }, 'commitTransientState': function (isCommitting) { this._transientState = null; this._isBrandNew = false; }, //------------------------------------------------------------------------- 'originalConfiguration': function () { return this.transientState()['original_configuration']; }, 'setOriginalConfiguration': function (aConfiguration) { this.transientState()['original_configuration'] = Clipperz.Base.deepClone(aConfiguration); }, //========================================================================= 'actualKey': function (aValueKey) { var actualKey; actualKey = 'directLogins' + '.' + this.reference(); if (aValueKey != '') { actualKey = actualKey + '.' + aValueKey; } return actualKey; }, //------------------------------------------------------------------------- 'getValue': function (aValueKey) { return this.record().getValue(this.actualKey(aValueKey)); }, 'setValue': function (aValueKey, aValue) { // return this.record().setValue(this.actualKey(aValueKey), aValue); return Clipperz.Async.callbacks("DirectLogin.setValue", [ MochiKit.Base.method(this, 'getValue', ''), MochiKit.Base.bind(function (aValue) { if (this.originalConfiguration() == null) { this.setOriginalConfiguration(aValue); } }, this), // MochiKit.Base.method(this, 'originalConfiguration'), // Clipperz.Async.deferredIf("originalConfiguration has been set", [ // ], [ // MochiKit.Base.method(this, 'getValue', ''), // MochiKit.Base.method(this, 'setOriginalConfiguration') // ]), MochiKit.Base.method(this.record(), 'setValue', this.actualKey(aValueKey), aValue) ], {trace:false}); }, 'removeValue': function (aValueKey) { // return this.record().removeValue(this.actualKey(aValueKey)); return Clipperz.Async.callbacks("DirectLogin.setValue", [ MochiKit.Base.method(this, 'originalConfiguration'), Clipperz.Async.deferredIf("originalConfiguration has been set", [ ], [ MochiKit.Base.method(this, 'getValue', ''), MochiKit.Base.method(this, 'setOriginalConfiguration') ]), MochiKit.Base.method(this.record(), 'removeValue', this.actualKey(aValueKey)) ], {trace:false}); }, //========================================================================= 'deleteAllCleanTextData': function () { this._inputs = null; this._bindings = null; this._formValues = null; this.resetTransientState(); }, //------------------------------------------------------------------------- 'hasAnyCleanTextData': function () { var result; result = false; result = result || (this._inputs != null); result = result || (this._bindings != null); result = result || (this._formValues != null); result = result || (MochiKit.Base.keys(this.transientState()).length != 0); return MochiKit.Async.succeed(result); }, //========================================================================= __syntaxFix__: "syntax fix" }); //############################################################################# Clipperz.PM.DataModel.DirectLogin.exception = { 'WrongBookmarkletConfiguration': new MochiKit.Base.NamedError("Clipperz.PM.DataModel.DirectLogin.exception.WrongBookmarkletConfiguration") }; Clipperz.PM.DataModel.DirectLogin.checkBookmarkletConfiguration = function(aConfiguration) { var configuration; try { configuration = Clipperz.Base.evalJSON(aConfiguration); // configuration = Clipperz.PM.BookmarkletProcessor.sanitizeBookmarkletConfiguration(configuration); if (MochiKit.Base.isUndefinedOrNull(configuration['page']['title']) || MochiKit.Base.isUndefinedOrNull(configuration['form']['attributes']['action']) // || MochiKit.Base.isUndefinedOrNull(configuration['form']['attributes']['method']) || MochiKit.Base.isUndefinedOrNull(configuration['form']['inputs']) || MochiKit.Base.isUndefinedOrNull(configuration['version']) ) { throw Clipperz.PM.DataModel.DirectLogin.exception.WrongBookmarkletConfiguration; } // if (MochiKit.Base.isUndefinedOrNull(configuration['favicon'])) { // throw Clipperz.PM.DataModel.DirectLogin.exception.WrongBookmarkletConfiguration; // } } catch (exception) { throw exception; } return configuration; }; diff --git a/frontend/gamma/js/Clipperz/PM/DataModel/DirectLoginBinding.js b/frontend/gamma/js/Clipperz/PM/DataModel/DirectLoginBinding.js index 4377853..a8ebb97 100644 --- a/frontend/gamma/js/Clipperz/PM/DataModel/DirectLoginBinding.js +++ b/frontend/gamma/js/Clipperz/PM/DataModel/DirectLoginBinding.js @@ -1,122 +1,120 @@ /* -Copyright 2008-2011 Clipperz Srl +Copyright 2008-2013 Clipperz Srl -This file is part of Clipperz Community Edition. -Clipperz Community Edition is an online password manager. +This file is part of Clipperz, the online password manager. For further information about its features and functionalities please refer to http://www.clipperz.com. -* Clipperz Community Edition is free software: you can redistribute - it and/or modify it under the terms of the GNU Affero General Public - License as published by the Free Software Foundation, either version - 3 of the License, or (at your option) any later version. +* Clipperz is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. -* Clipperz Community Edition is distributed in the hope that it will - be useful, but WITHOUT ANY WARRANTY; without even the implied - warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* Clipperz is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. * You should have received a copy of the GNU Affero General Public - License along with Clipperz Community Edition. If not, see - <http://www.gnu.org/licenses/>. + License along with Clipperz. If not, see http://www.gnu.org/licenses/. */ if (typeof(Clipperz) == 'undefined') { Clipperz = {}; } if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; } if (typeof(Clipperz.PM.DataModel) == 'undefined') { Clipperz.PM.DataModel = {}; } //############################################################################# Clipperz.PM.DataModel.DirectLoginBinding = function(aDirectLogin, args) { args = args || {}; this._directLogin = aDirectLogin|| Clipperz.Base.exception.raise('MandatoryParameter'); this._key = args.key || Clipperz.Base.exception.raise('MandatoryParameter'); this._fieldKey = args.field || /* this.directLogin().fieldWithName(args.fieldName).reference() || */ null; return this; } Clipperz.PM.DataModel.DirectLoginBinding.prototype = MochiKit.Base.update(null, { 'toString': function() { return "DirectLoginBinding (" + this.key() + ", " + this.fieldKey() + ")"; }, //------------------------------------------------------------------------- 'directLogin': function () { return this._directLogin; }, //------------------------------------------------------------------------- 'key': function() { return this._key; }, //------------------------------------------------------------------------- 'fieldKey': function() { return this._fieldKey; }, 'setFieldKey': function(aValue) { this._fieldKey = aValue; return this.directLogin().setValue('bindingData' + '.' + this.key(), aValue); }, // 'fieldName': function() { // return this._fieldName; // }, //------------------------------------------------------------------------- 'field': function() { var deferredResult; if (this.fieldKey() != null) { deferredResult = Clipperz.Async.callbacks("DirectLoginBinding.field [1]", [ MochiKit.Base.method(this.directLogin().record(), 'fields'), MochiKit.Base.itemgetter(this.fieldKey()) ], {trace:false}); // } else if (this.fieldName() != null) { // WTF = TODO; // result = this.directLogin().record().fieldWithName(this.fieldName()); // // this.setFieldKey(result.key()); } else { deferredResult = MochiKit.Async.succeed(null); } return deferredResult; }, 'setField': function (aField) { this.setFieldKey(aField.reference()); }, //------------------------------------------------------------------------- /* 'fieldValue': function () { return Clipperz.Async.callbacks("DirectLoginBinding.fieldValue", [ MochiKit.Base.method('field'), MochiKit.Base.methodcaller('value') ], {trace:false}); }, */ //------------------------------------------------------------------------- 'serializedData': function() { return this.fieldKey(); }, //------------------------------------------------------------------------- __syntaxFix__: "syntax fix" }); diff --git a/frontend/gamma/js/Clipperz/PM/DataModel/DirectLoginFormValue.js b/frontend/gamma/js/Clipperz/PM/DataModel/DirectLoginFormValue.js index a461197..2429f88 100644 --- a/frontend/gamma/js/Clipperz/PM/DataModel/DirectLoginFormValue.js +++ b/frontend/gamma/js/Clipperz/PM/DataModel/DirectLoginFormValue.js @@ -1,104 +1,101 @@ /* -Copyright 2008-2011 Clipperz Srl +Copyright 2008-2013 Clipperz Srl -This file is part of Clipperz Community Edition. -Clipperz Community Edition is an online password manager. +This file is part of Clipperz, the online password manager. For further information about its features and functionalities please refer to http://www.clipperz.com. -* Clipperz Community Edition is free software: you can redistribute - it and/or modify it under the terms of the GNU Affero General Public - License as published by the Free Software Foundation, either version - 3 of the License, or (at your option) any later version. +* Clipperz is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. -* Clipperz Community Edition is distributed in the hope that it will - be useful, but WITHOUT ANY WARRANTY; without even the implied - warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* Clipperz is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. * You should have received a copy of the GNU Affero General Public - License along with Clipperz Community Edition. If not, see - <http://www.gnu.org/licenses/>. + License along with Clipperz. If not, see http://www.gnu.org/licenses/. */ if (typeof(Clipperz) == 'undefined') { Clipperz = {}; } if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; } if (typeof(Clipperz.PM.DataModel) == 'undefined') { Clipperz.PM.DataModel = {}; } //############################################################################# Clipperz.PM.DataModel.DirectLoginFormValue = function(aDirectLogin, args) { args = args || {}; this._directLogin = aDirectLogin|| Clipperz.Base.exception.raise('MandatoryParameter'); this._key = args.key || Clipperz.Base.exception.raise('MandatoryParameter'); this._fieldOptions = args.fieldOptions || Clipperz.Base.exception.raise('MandatoryParameter'); this._value = args.value || null; return this; } Clipperz.PM.DataModel.DirectLoginFormValue.prototype = MochiKit.Base.update(null, { 'toString': function() { return "DirectLoginFormValue (" + this.key() + ", " + this.value() + ")"; }, //------------------------------------------------------------------------- 'directLogin': function () { return this._directLogin; }, //------------------------------------------------------------------------- 'key': function() { return this._key; }, //------------------------------------------------------------------------- 'fieldOptions': function() { return this._fieldOptions; }, //------------------------------------------------------------------------- 'type': function () { return this.fieldOptions()['type']; }, //------------------------------------------------------------------------- 'value': function() { var result; result = this._value; // if ((result == null) && (this.type() == 'checkbox')) { // result = false; // }; return result; }, 'setValue': function (aValue) { -//console.log("DirectLoginFormValue.setValue", aValue); this._value = aValue; return this.directLogin().setValue('formValues' + '.' + this.key(), aValue); }, //------------------------------------------------------------------------- /* 'serializedData': function() { return this.value(); }, */ //------------------------------------------------------------------------- __syntaxFix__: "syntax fix" }); diff --git a/frontend/gamma/js/Clipperz/PM/DataModel/DirectLoginInput.js b/frontend/gamma/js/Clipperz/PM/DataModel/DirectLoginInput.js index 8188389..d9995fc 100644 --- a/frontend/gamma/js/Clipperz/PM/DataModel/DirectLoginInput.js +++ b/frontend/gamma/js/Clipperz/PM/DataModel/DirectLoginInput.js @@ -1,200 +1,192 @@ /* -Copyright 2008-2011 Clipperz Srl +Copyright 2008-2013 Clipperz Srl -This file is part of Clipperz Community Edition. -Clipperz Community Edition is an online password manager. +This file is part of Clipperz, the online password manager. For further information about its features and functionalities please refer to http://www.clipperz.com. -* Clipperz Community Edition is free software: you can redistribute - it and/or modify it under the terms of the GNU Affero General Public - License as published by the Free Software Foundation, either version - 3 of the License, or (at your option) any later version. +* Clipperz is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. -* Clipperz Community Edition is distributed in the hope that it will - be useful, but WITHOUT ANY WARRANTY; without even the implied - warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* Clipperz is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. * You should have received a copy of the GNU Affero General Public - License along with Clipperz Community Edition. If not, see - <http://www.gnu.org/licenses/>. + License along with Clipperz. If not, see http://www.gnu.org/licenses/. */ if (typeof(Clipperz) == 'undefined') { Clipperz = {}; } if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; } if (typeof(Clipperz.PM.DataModel) == 'undefined') { Clipperz.PM.DataModel = {}; } //############################################################################# Clipperz.PM.DataModel.DirectLoginInput = function(args) { this._args = args; return this; } Clipperz.PM.DataModel.DirectLoginInput.prototype = MochiKit.Base.update(null, { 'args': function() { return this._args; }, //------------------------------------------------------------------------- 'name': function() { return this.args()['name']; }, //------------------------------------------------------------------------- 'type': function() { var result; result = this.args()['type']; if (result != null) { result = result.toLowerCase(); } return result; }, //------------------------------------------------------------------------- 'options': function() { return this.args()['options']; }, //------------------------------------------------------------------------- 'value': function() { return this.args()['value']; }, //------------------------------------------------------------------------- /* 'formConfiguration': function(someFormValues, someBindings, someFields) { var result; -//console.log("### DirectLoginInput.formConfiguration", someFields); + if (this.shouldSetValue()) { switch (this.type()) { case 'select': var currentValue; var options; // currentValue = this.directLogin()._configuration['formValues'][this.name()]; currentValue = someFormValues[this.name()]; options = this.args()['options']; result = MochiKit.DOM.SELECT({name:this.name()}, MochiKit.Base.map(function(anOption) { var options; options = {value:anOption['value']}; if (currentValue == anOption['value']) { options.selected = true; } return MochiKit.DOM.OPTION(options, anOption['label']) }, options) ) break; case 'checkbox': var options; options = {type:'checkbox', name: this.name()}; // if (this.directLogin()._configuration['formValues'][this.name()] == true) { if (someFormValues[this.name()] == true) { options['checked'] = true; }; result = MochiKit.DOM.INPUT(options, null); break; case 'radio': var currentName; var currentValue; var options; currentName = this.name(); // currentValue = this.directLogin()._configuration['formValues'][this.name()]; currentValue = someFormValues[this.name()]; options = this.args()['options']; result = MochiKit.DOM.DIV(null, MochiKit.Base.map(function(anOption) { var options; var isChecked; var inputNode; var divNode; options = {type:'radio', name:currentName, value:anOption['value']} isChecked = (currentValue == anOption['value']); if (isChecked) { options.checked = true; } if (Clipperz_IEisBroken == true) { var checkedValue; checkedValue = (isChecked ? " CHECKED" : ""); inputNode = MochiKit.DOM.currentDocument().createElement("<INPUT TYPE='RADIO' NAME='" + currentName + "' VALUE='" + anOption['value'] + "'" + checkedValue + ">"); } else { inputNode = MochiKit.DOM.INPUT(options, anOption['value']); } divNode = MochiKit.DOM.DIV(null, inputNode); return divNode; }, options) ); break; } } else { var binding; // binding = this.directLogin().bindings()[this.name()]; binding = someBindings[this.name()]; -//console.log("### binding", binding); -//if (binding != null) { -/// console.log(" binding.field()", binding.field()); -/// console.log(" binding.field().value()", binding.field().value()); -// console.log(" someFields[binding.fieldKey()].value()", someFields[binding.fieldKey()].value()); -//} result = MochiKit.DOM.INPUT({ type:((this.type() != 'password') ? this.type() : 'text'), name:this.name(), // value:((binding != null)? binding.field().value() : this.value()) value:((binding != null)? someFields[binding.fieldKey()]['value'] : this.value()) // value:((binding != null)? someFields[binding.fieldKey()].value() : this.value()) }, null); } return result; }, */ //------------------------------------------------------------------------- 'needsFormValue': function() { var type; var result; type = this.type(); result = ((type == 'checkbox') || (type == 'radio') || (type == 'select')); return result; }, 'needsBinding': function() { var type; var result; type = this.type(); result = ((type == 'text') || (type == 'password')); return result; }, //------------------------------------------------------------------------- __syntaxFix__: "syntax fix" }); diff --git a/frontend/gamma/js/Clipperz/PM/DataModel/EncryptedRemoteObject.js b/frontend/gamma/js/Clipperz/PM/DataModel/EncryptedRemoteObject.js index cdeec8b..1aa7a52 100644 --- a/frontend/gamma/js/Clipperz/PM/DataModel/EncryptedRemoteObject.js +++ b/frontend/gamma/js/Clipperz/PM/DataModel/EncryptedRemoteObject.js @@ -1,548 +1,542 @@ /* -Copyright 2008-2011 Clipperz Srl +Copyright 2008-2013 Clipperz Srl -This file is part of Clipperz Community Edition. -Clipperz Community Edition is an online password manager. +This file is part of Clipperz, the online password manager. For further information about its features and functionalities please refer to http://www.clipperz.com. -* Clipperz Community Edition is free software: you can redistribute - it and/or modify it under the terms of the GNU Affero General Public - License as published by the Free Software Foundation, either version - 3 of the License, or (at your option) any later version. +* Clipperz is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. -* Clipperz Community Edition is distributed in the hope that it will - be useful, but WITHOUT ANY WARRANTY; without even the implied - warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* Clipperz is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. * You should have received a copy of the GNU Affero General Public - License along with Clipperz Community Edition. If not, see - <http://www.gnu.org/licenses/>. + License along with Clipperz. If not, see http://www.gnu.org/licenses/. */ try { if (typeof(Clipperz.KeyValueObjectStore) == 'undefined') { throw ""; }} catch (e) { throw "Clipperz.PM.DataModel.EncryptedRemoteObject depends on Clipperz.KeyValueObjectStore!"; } if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; } if (typeof(Clipperz.PM.DataModel) == 'undefined') { Clipperz.PM.DataModel = {}; } Clipperz.PM.DataModel.EncryptedRemoteObject = function(args) { args = args || {}; this._name = args.name || null; this._reference = args.reference || Clipperz.PM.Crypto.randomKey(); this._isBrandNew = ((args.reference == null) && (args.remoteData == null)); if ((this._isBrandNew == false) && (args['retrieveKeyFunction'] == null)) { Clipperz.Base.exception.raise('MandatoryParameter'); } else { this._retrieveKeyFunction = args['retrieveKeyFunction']; } this._retrieveRemoteDataFunction = args.retrieveRemoteDataFunction || null; this._remoteData = args.remoteData || null; // this._remoteData = args.remoteData ? Clipperz.Base.deepClone(args.remoteData) : null; if ((!this._isBrandNew) && ((this._retrieveRemoteDataFunction == null) && (this._remoteData == null))) { Clipperz.Base.exception.raise('MandatoryParameter'); } this._encryptedDataKeypath = args.encryptedDataKeypath || 'data'; //Clipperz.Base.exception.raise('MandatoryParameter'); this._encryptedVersionKeypath = args.encryptedVersionKeypath || 'version'; //Clipperz.Base.exception.raise('MandatoryParameter'); this._transientState = null; this._deferredLocks = {}; if (this._isBrandNew == true) { this._objectDataStore = new Clipperz.KeyValueObjectStore(/*{'name':'EncryptedRemoteObject.objectDataStore [1]'}*/); } else { this._objectDataStore = null; } return this; } // // Basic data workflow // ======================= // // getRemoteData // unpackRemoteData // getDecryptData [encryptedDataKeypath, encryptedVersionKeypath] // unpackData // // // ?? packData // ?? encryptDataWithKey // ?? packRemoteData [encryptedDataKeypath (?), encryptedVersionKeypath (?)] // Clipperz.PM.DataModel.EncryptedRemoteObject.prototype = MochiKit.Base.update(null, { 'toString': function () { return "Clipperz.PM.DataModel.EncryptedRemoteObject" + (this.name() != null ? " - " + this.name() : ""); }, //------------------------------------------------------------------------- 'name': function () { return this._name; }, //------------------------------------------------------------------------- 'reference': function () { return this._reference; }, 'setReference': function (aValue) { this._reference = aValue; return this._reference; }, //------------------------------------------------------------------------- 'transientState': function () { if (this._transientState == null) { this._transientState = new Clipperz.KeyValueObjectStore(/*{'name':'EncryptedRemoteObject.transientState [2]'}*/); } return this._transientState; }, 'resetTransientState': function (isCommitting) { if (this._transientState != null) { this._transientState.removeAllData(); } this._transientState = null; }, //------------------------------------------------------------------------- 'isBrandNew': function () { return this._isBrandNew; }, //------------------------------------------------------------------------- 'getKey': function () { var deferredResult; var deferredLock; deferredLock = this.getDeferredLockForKey('key'); deferredResult = new Clipperz.Async.Deferred("EncryptedRemoteObject.getKey", {trace:false}); deferredResult.acquireLock(deferredLock); deferredResult.addMethod( this.decryptedDataStore(), 'deferredGetOrSet', 'decryptionKey', MochiKit.Base.partial(this.retrieveKeyFunction(), this.reference()) ); deferredResult.releaseLock(deferredLock); deferredResult.callback(); return deferredResult; }, // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 'retrieveKeyFunction': function () { return this._retrieveKeyFunction; }, 'setRetrieveKeyFunction': function (aFunction) { this._retrieveKeyFunction = aFunction; }, //------------------------------------------------------------------------- 'hasLoadedRemoteData': function () { return (this._remoteData != null); }, 'getRemoteData': function () { var deferredResult; var deferredLock; deferredLock = this.getDeferredLockForKey('remoteData'); deferredResult = new Clipperz.Async.Deferred("EncryptedRemoteObjects.getRemoteData", {trace:false}); deferredResult.acquireLock(deferredLock); deferredResult.addCallback(MochiKit.Base.bind(function () { var innerDeferredResult; if (this._remoteData != null) { innerDeferredResult = MochiKit.Async.succeed(this._remoteData); } else { innerDeferredResult = Clipperz.Async.callbacks("EncryptedRemoteObjects.getRemoteData <inner deferred>", [ MochiKit.Base.partial(this.retrieveRemoteDataFunction(), this.reference()), MochiKit.Base.method(this, 'unpackRemoteData'), MochiKit.Base.bind(function (someData) { this._remoteData = someData; return this._remoteData; }, this) ], {trace:false}); } return innerDeferredResult; }, this)) deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress'); deferredResult.releaseLock(deferredLock); deferredResult.callback(); return deferredResult; }, //------------------------------------------------------------------------- 'unpackRemoteData': function (someData) { return MochiKit.Async.succeed(someData); }, //......................................................................... 'packRemoteData': function (someData) { var result; result = { 'reference': this.reference(), 'data': someData, 'version': Clipperz.PM.Crypto.encryptingFunctions.currentVersion }; return MochiKit.Async.succeed(result); }, //------------------------------------------------------------------------- 'retrieveRemoteDataFunction': function () { return this._retrieveRemoteDataFunction; }, 'setRetrieveRemoteDataFunction': function (aFunction) { this._retrieveRemoteDataFunction = aFunction; }, //------------------------------------------------------------------------- 'decryptedDataStore': function () { if (this._decryptedDataStore == null) { this._decryptedDataStore = new Clipperz.KeyValueObjectStore(/*{'name':'EncryptedRemoteObject.decryptedDataStore [3]'}*/); }; return this._decryptedDataStore; }, //......................................................................... 'getDecryptedData': function () { var deferredResult; var deferredLock; deferredLock = this.getDeferredLockForKey('decryptedData'); deferredResult = new Clipperz.Async.Deferred("EncryptedRemoteObject.getDecryptedData", {trace:false}); deferredResult.acquireLock(deferredLock); deferredResult.addMethod(this, 'decryptedDataStore'); deferredResult.addCallback(MochiKit.Base.methodcaller('deferredGetOrSet', 'decryptedData', MochiKit.Base.bind(function () { var innerDeferredResult; innerDeferredResult = new Clipperz.Async.Deferred("EncryptedRemoteObject.getDecryptedData <inner deferred>", {trace:false}); innerDeferredResult.addMethod(this, 'getRemoteData'); innerDeferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress'); innerDeferredResult.collectResults({ 'key': MochiKit.Base.method(this, 'getKey'), 'value': MochiKit.Base.itemgetter(this._encryptedDataKeypath), 'version': MochiKit.Base.itemgetter(this._encryptedVersionKeypath) }); innerDeferredResult.addCallback(Clipperz.PM.Crypto.deferredDecrypt); innerDeferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress'); innerDeferredResult.addMethod(this, 'unpackData'); innerDeferredResult.callback(); return innerDeferredResult; }, this))); deferredResult.releaseLock(deferredLock); deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress'); deferredResult.callback(); return deferredResult; }, //------------------------------------------------------------------------- 'setValue': function(aKey, aValue) { var deferredResult; deferredResult = new Clipperz.Async.Deferred("EncryptedRemoteObject.setValue", {trace:false}); deferredResult.addMethod(this, '_getObjectDataStore'); deferredResult.addCallback(MochiKit.Base.methodcaller('setValue', aKey, aValue)); deferredResult.callback(); return deferredResult; }, //......................................................................... 'getValue': function (aKey) { return Clipperz.Async.callbacks("EncryptedRemoteObject.getValue", [ MochiKit.Base.method(this, '_getObjectDataStore'), MochiKit.Base.methodcaller('getValue', aKey) ], {trace:false}); }, //......................................................................... 'removeValue': function (aKey) { return Clipperz.Async.callbacks("EncryptedRemoteObject.removeValue", [ MochiKit.Base.method(this, '_getObjectDataStore'), MochiKit.Base.methodcaller('removeValue', aKey) ], {trace:false}); }, //......................................................................... 'values': function () { return Clipperz.Async.callbacks("EncryptedRemoteObject.values", [ MochiKit.Base.method(this, '_getObjectDataStore'), MochiKit.Base.methodcaller('values') ], {trace:false}); }, 'setValues': function (someValues) { return Clipperz.Async.callbacks("EncryptedRemoteObject.values", [ MochiKit.Base.method(this, '_getObjectDataStore'), MochiKit.Base.methodcaller('setValues', someValues) ], {trace:false}); }, //......................................................................... '_getObjectDataStore': function () { var deferredResult; var deferredLock; deferredLock = this.getDeferredLockForKey('objectDataStore'); deferredResult = new Clipperz.Async.Deferred("EncryptedRemoteObject._getObjectDataStore", {trace:false}); deferredResult.acquireLock(deferredLock); deferredResult.addCallback(MochiKit.Base.bind(function () { var innerDeferredResult; if (this._objectDataStore == null) { this._objectDataStore = new Clipperz.KeyValueObjectStore(/*{'name':'EncryptedRemoteObject.objectDataStore [4]'}*/); innerDeferredResult = new Clipperz.Async.Deferred("EncryptedRemoteObject._getObjectDataStore <inner deferred>", {trace:false}); innerDeferredResult.addMethod(this, 'getDecryptedData'); innerDeferredResult.addMethod(this._objectDataStore, 'initWithValues'); innerDeferredResult.callback(); } else { innerDeferredResult = MochiKit.Async.succeed(this._objectDataStore); } return innerDeferredResult; }, this)); deferredResult.releaseLock(deferredLock); deferredResult.callback(); return deferredResult; }, 'hasInitiatedObjectDataStore': function () { return (this._objectDataStore != null); }, //------------------------------------------------------------------------- 'getDeferredLockForKey': function (aKey) { var result; result = this._deferredLocks[aKey]; if (typeof(result) == 'undefined') { result = new MochiKit.Async.DeferredLock(); this._deferredLocks[aKey] = result; } return result; }, //------------------------------------------------------------------------- 'unpackData': function (someData) { // ++ return someData; }, 'packData': function (someData) { // ++ return someData; }, //------------------------------------------------------------------------- 'hasPendingChanges': function () { var deferredResult; var tempObj = this; if (this.isBrandNew()) { // deferredResult = MochiKit.Async.succeed(true); deferredResult = this.hasPendingChangesWhenBrandNew(); } else if (this.hasInitiatedObjectDataStore()) { deferredResult = new Clipperz.Async.Deferred("EncryptedRemoteObject.hasPendingChanges", {trace:false}); deferredResult.collectResults({ 'decryptedData': [ MochiKit.Base.method(this, 'getDecryptedData'), Clipperz.Base.serializeJSON ], 'objectData': [ MochiKit.Base.method(this, '_getObjectDataStore'), MochiKit.Base.methodcaller('values'), Clipperz.Base.serializeJSON ] }); deferredResult.addCallback(function (someValues) { -//if (someValues['decryptedData'] != someValues['objectData']) { -// console.log("ORIGINAL DATA", '[[[' + someValues['decryptedData'] + ']]]'); -// console.log("CURRENT DATA", '>>>' + someValues['objectData'] + '<<<'); -//} return (someValues['decryptedData'] != someValues['objectData']); }); deferredResult.callback(); } else { deferredResult = MochiKit.Async.succeed(false); } return deferredResult; }, 'hasPendingChangesWhenBrandNew': function () { return MochiKit.Async.succeed(true); }, //------------------------------------------------------------------------- 'commitTransientState': function () { var deferredResult; // if (this.transientState().getValue('__prepareRemoteData') == true) { if (this.transientState().getValue('packedRemoteData') != null) { deferredResult = Clipperz.Async.callbacks("EncryptedRemoteObject.commitTransientState - prepareRemoteData", [ MochiKit.Base.bind(function (someData) { this._remoteData = this.transientState().getValue('packedRemoteData'); }, this), MochiKit.Base.method(this, '_getObjectDataStore'), MochiKit.Base.methodcaller('values'), Clipperz.Base.deepClone, MochiKit.Base.method(this.decryptedDataStore(), 'setValue', 'decryptedData'), MochiKit.Base.method(this, 'resetTransientState', true) ], {trace:false}); } else { deferredResult = Clipperz.Async.callbacks("EncryptedRemoteObject.commitTransientState - NO prepareRemoteData", [ MochiKit.Base.method(this, 'resetTransientState', true) ], {trace:false}); } this._isBrandNew = false; return deferredResult; }, //------------------------------------------------------------------------- 'revertChanges': function () { if (this.hasInitiatedObjectDataStore()) { this._objectDataStore.removeAllData(); this._objectDataStore = null; } this.resetTransientState(false); return MochiKit.Async.succeed(); }, //------------------------------------------------------------------------- 'deleteAllCleanTextData': function () { var deferredResult; deferredResult = new Clipperz.Async.Deferred("EncryptedRemoteObject.deleteAllCleanTextData", {trace:false}); deferredResult.addMethod(this, 'resetTransientState', false); deferredResult.acquireLock(this.getDeferredLockForKey('decryptedData')); deferredResult.addCallback(MochiKit.Base.bind(function () { if (this._decryptedDataStore != null) { this._decryptedDataStore.removeAllData(); } }, this)); deferredResult.releaseLock(this.getDeferredLockForKey('decryptedData')); deferredResult.acquireLock(this.getDeferredLockForKey('objectDataStore')); deferredResult.addCallback(MochiKit.Base.bind(function () { if (this._objectDataStore != null) { this._objectDataStore.removeAllData(); this._objectDataStore = null; } }, this)); deferredResult.releaseLock(this.getDeferredLockForKey('objectDataStore')); deferredResult.callback(); return deferredResult; }, //......................................................................... 'hasAnyCleanTextData': function () { var result; result = false; result = result || (! this.decryptedDataStore().isEmpty()); result = result || (! this.transientState().isEmpty()); if (this.hasInitiatedObjectDataStore()) { result = result || (! this._objectDataStore.isEmpty()); } return MochiKit.Async.succeed(result); }, //------------------------------------------------------------------------- 'prepareRemoteDataWithKey': function (aKey) { return Clipperz.Async.callbacks("EncryptedRemoteObject.prepareRemoteDataWithKey", [ // MochiKit.Base.method(this.transientState(), 'setValue', '__prepareRemoteData', true), MochiKit.Base.method(this, '_getObjectDataStore'), MochiKit.Base.methodcaller('values'), MochiKit.Base.method(this, 'packData'), function (someData) { return Clipperz.PM.Crypto.deferredEncrypt({ 'key': aKey, 'value': someData, 'version': Clipperz.PM.Crypto.encryptingFunctions.currentVersion }) }, MochiKit.Base.method(this, 'packRemoteData'), MochiKit.Base.method(this.transientState(), 'setValue', 'packedRemoteData'), function (someData) { MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'advanceProgress'); return someData; } ], {trace:false}); }, //------------------------------------------------------------------------- __syntaxFix__: "syntax fix" }); diff --git a/frontend/gamma/js/Clipperz/PM/DataModel/OneTimePassword.js b/frontend/gamma/js/Clipperz/PM/DataModel/OneTimePassword.js index 834e21b..fbca1ff 100644 --- a/frontend/gamma/js/Clipperz/PM/DataModel/OneTimePassword.js +++ b/frontend/gamma/js/Clipperz/PM/DataModel/OneTimePassword.js @@ -1,354 +1,350 @@ /* -Copyright 2008-2011 Clipperz Srl +Copyright 2008-2013 Clipperz Srl -This file is part of Clipperz Community Edition. -Clipperz Community Edition is an online password manager. +This file is part of Clipperz, the online password manager. For further information about its features and functionalities please refer to http://www.clipperz.com. -* Clipperz Community Edition is free software: you can redistribute - it and/or modify it under the terms of the GNU Affero General Public - License as published by the Free Software Foundation, either version - 3 of the License, or (at your option) any later version. +* Clipperz is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. -* Clipperz Community Edition is distributed in the hope that it will - be useful, but WITHOUT ANY WARRANTY; without even the implied - warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* Clipperz is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. * You should have received a copy of the GNU Affero General Public - License along with Clipperz Community Edition. If not, see - <http://www.gnu.org/licenses/>. + License along with Clipperz. If not, see http://www.gnu.org/licenses/. */ if (typeof(Clipperz) == 'undefined') { Clipperz = {}; } if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; } if (typeof(Clipperz.PM.DataModel) == 'undefined') { Clipperz.PM.DataModel = {}; } //############################################################################# Clipperz.PM.DataModel.OneTimePassword = function(args) { args = args || {}; // this._user = args['user']; this._reference = args['reference'] || Clipperz.PM.Crypto.randomKey(); this._password = args['password']; this._passwordValue = Clipperz.PM.DataModel.OneTimePassword.normalizedOneTimePassword(args['password']); this._creationDate = args['created'] ? Clipperz.PM.Date.parseDateWithUTCFormat(args['created']) : new Date(); this._usageDate = args['used'] ? Clipperz.PM.Date.parseDateWithUTCFormat(args['used']) : null; this._status = args['status'] || 'ACTIVE'; // 'REQUESTED', 'USED', 'DISABLED' this._connectionInfo= null; this._key = null; this._keyChecksum = null; return this; } Clipperz.PM.DataModel.OneTimePassword.prototype = MochiKit.Base.update(null, { 'toString': function() { return "Clipperz.PM.DataModel.OneTimePassword"; }, /* //------------------------------------------------------------------------- 'user': function() { return this._user; }, //------------------------------------------------------------------------- 'password': function() { return this._password; }, //------------------------------------------------------------------------- 'passwordValue': function() { return this._passwordValue; }, //------------------------------------------------------------------------- 'creationDate': function() { return this._creationDate; }, //------------------------------------------------------------------------- 'reference': function() { return this._reference; }, //------------------------------------------------------------------------- 'key': function() { if (this._key == null) { this._key = Clipperz.PM.DataModel.OneTimePassword.computeKeyWithUsernameAndPassword(this.user().username(), this.passwordValue()); } return this._key; }, //------------------------------------------------------------------------- 'keyChecksum': function() { if (this._keyChecksum == null) { this._keyChecksum = Clipperz.PM.DataModel.OneTimePassword.computeKeyChecksumWithUsernameAndPassword(this.user().username(), this.passwordValue()); } return this._keyChecksum; }, */ //------------------------------------------------------------------------- 'status': function() { return this._status; }, 'setStatus': function(aValue) { this._status = aValue; }, //------------------------------------------------------------------------- /* 'serializedData': function() { var result; result = { 'password': this.password(), 'created': this.creationDate() ? Clipperz.PM.Date.formatDateWithUTCFormat(this.creationDate()) : null, 'used': this.usageDate() ? Clipperz.PM.Date.formatDateWithUTCFormat(this.usageDate()) : null, 'status': this.status() }; return result; }, //------------------------------------------------------------------------- 'packedPassphrase': function() { var result; var packedPassphrase; var encodedPassphrase; var prefixPadding; var suffixPadding; var getRandomBytes; getRandomBytes = MochiKit.Base.method(Clipperz.Crypto.PRNG.defaultRandomGenerator(), 'getRandomBytes'); encodedPassphrase = new Clipperz.ByteArray(this.user().passphrase()).toBase64String(); -//MochiKit.Logging.logDebug("--- encodedPassphrase.length: " + encodedPassphrase.length); +//Clipperz.logDebug("--- encodedPassphrase.length: " + encodedPassphrase.length); prefixPadding = getRandomBytes(getRandomBytes(1).byteAtIndex(0)).toBase64String(); -//MochiKit.Logging.logDebug("--- prefixPadding.length: " + prefixPadding.length); +//Clipperz.logDebug("--- prefixPadding.length: " + prefixPadding.length); suffixPadding = getRandomBytes((500 - prefixPadding.length - encodedPassphrase.length) * 6 / 8).toBase64String(); -//MochiKit.Logging.logDebug("--- suffixPadding.length: " + suffixPadding.length); -//MochiKit.Logging.logDebug("--- total.length: " + (prefixPadding.length + encodedPassphrase.length + suffixPadding.length)); +//Clipperz.logDebug("--- suffixPadding.length: " + suffixPadding.length); +//Clipperz.logDebug("--- total.length: " + (prefixPadding.length + encodedPassphrase.length + suffixPadding.length)); packedPassphrase = { 'prefix': prefixPadding, 'passphrase': encodedPassphrase, 'suffix': suffixPadding }; // result = Clipperz.Base.serializeJSON(packedPassphrase); result = packedPassphrase; -//MochiKit.Logging.logDebug("===== OTP packedPassprase: [" + result.length + "]" + result); -//MochiKit.Logging.logDebug("<<< OneTimePassword.packedPassphrase"); +//Clipperz.logDebug("===== OTP packedPassprase: [" + result.length + "]" + result); +//Clipperz.logDebug("<<< OneTimePassword.packedPassphrase"); return result; }, //------------------------------------------------------------------------- 'encryptedPackedPassphrase': function() { return Clipperz.PM.Crypto.deferredEncryptWithCurrentVersion(this.passwordValue(), this.packedPassphrase()) }, //------------------------------------------------------------------------- 'encryptedData': function() { var deferredResult; var result; -//MochiKit.Logging.logDebug(">>> OneTimePassword.encryptedData"); -//MochiKit.Logging.logDebug("--- OneTimePassword.encryptedData - id: " + this.reference()); +//Clipperz.logDebug(">>> OneTimePassword.encryptedData"); +//Clipperz.logDebug("--- OneTimePassword.encryptedData - id: " + this.reference()); result = { 'reference': this.reference(), 'key': this.key(), 'keyChecksum': this.keyChecksum(), 'data': "", 'version': Clipperz.PM.Crypto.encryptingFunctions.currentVersion } -//MochiKit.Logging.logDebug("--- OneTimePassword.encryptedData - 2: " + Clipperz.Base.serializeJSON(result)); +//Clipperz.logDebug("--- OneTimePassword.encryptedData - 2: " + Clipperz.Base.serializeJSON(result)); deferredResult = new MochiKit.Async.Deferred(); -//MochiKit.Logging.logDebug("--- OneTimePassword.encryptedData - 3"); -//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("OneTimePassword.encryptedData - 1: " + res); return res;}); +//Clipperz.logDebug("--- OneTimePassword.encryptedData - 3"); +//deferredResult.addBoth(function(res) {Clipperz.logDebug("OneTimePassword.encryptedData - 1: " + res); return res;}); //# deferredResult.addCallback(Clipperz.PM.Crypto.deferredEncryptWithCurrentVersion, this.passwordValue(), this.packedPassphrase()); deferredResult.addCallback(MochiKit.Base.method(this, 'encryptedPackedPassphrase')); -//MochiKit.Logging.logDebug("--- OneTimePassword.encryptedData - 4"); -//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("OneTimePassword.encryptedData - 2: [" + res.length + "]" + res); return res;}); +//Clipperz.logDebug("--- OneTimePassword.encryptedData - 4"); +//deferredResult.addBoth(function(res) {Clipperz.logDebug("OneTimePassword.encryptedData - 2: [" + res.length + "]" + res); return res;}); deferredResult.addCallback(function(aResult, res) { aResult['data'] = res; return aResult; }, result); -//MochiKit.Logging.logDebug("--- OneTimePassword.encryptedData - 5"); -//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("OneTimePassword.encryptedData - 3: " + Clipperz.Base.serializeJSON(res)); return res;}); +//Clipperz.logDebug("--- OneTimePassword.encryptedData - 5"); +//deferredResult.addBoth(function(res) {Clipperz.logDebug("OneTimePassword.encryptedData - 3: " + Clipperz.Base.serializeJSON(res)); return res;}); deferredResult.callback(); -//MochiKit.Logging.logDebug("--- OneTimePassword.encryptedData - 6"); +//Clipperz.logDebug("--- OneTimePassword.encryptedData - 6"); return deferredResult; }, //------------------------------------------------------------------------- 'saveChanges': function() { var deferredResult; var result; -//MochiKit.Logging.logDebug(">>> OneTimePassword.saveChanges"); +//Clipperz.logDebug(">>> OneTimePassword.saveChanges"); result = {}; deferredResult = new MochiKit.Async.Deferred(); deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'saveOTP_encryptUserData'); deferredResult.addCallback(MochiKit.Base.method(this.user(), 'encryptedData')); deferredResult.addCallback(function(aResult, res) { aResult['user'] = res; return aResult; }, result); deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'saveOTP_encryptOTPData'); deferredResult.addCallback(MochiKit.Base.method(this, 'encryptedData')); deferredResult.addCallback(function(aResult, res) { aResult['oneTimePassword'] = res; return aResult; }, result); deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'saveOTP_sendingData'); -//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("OneTimePassword.saveChanges - 1: " + Clipperz.Base.serializeJSON(res)); return res;}); +//deferredResult.addBoth(function(res) {Clipperz.logDebug("OneTimePassword.saveChanges - 1: " + Clipperz.Base.serializeJSON(res)); return res;}); deferredResult.addCallback(MochiKit.Base.method(this.user().connection(), 'message'), 'addNewOneTimePassword'); deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'saveOTP_updatingInterface'); -//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("OneTimePassword.saveChanges - 2: " + res); return res;}); +//deferredResult.addBoth(function(res) {Clipperz.logDebug("OneTimePassword.saveChanges - 2: " + res); return res;}); deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'notify', 'OTPUpdated'); deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'oneTimePassword_saveChanges_done', null); -//deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug("OneTimePassword.saveChanges - 2: " + res); return res;}); +//deferredResult.addBoth(function(res) {Clipperz.logDebug("OneTimePassword.saveChanges - 2: " + res); return res;}); deferredResult.callback(); -//MochiKit.Logging.logDebug("<<< OneTimePassword.saveChanges"); +//Clipperz.logDebug("<<< OneTimePassword.saveChanges"); return deferredResult; }, //------------------------------------------------------------------------- 'usageDate': function() { return this._usageDate; }, 'setUsageDate': function(aValue) { this._usageDate = aValue; }, //------------------------------------------------------------------------- 'connectionInfo': function() { return this._connectionInfo; }, 'setConnectionInfo': function(aValue) { this._connectionInfo = aValue; }, //------------------------------------------------------------------------- 'isExpired': function() { return (this.usageDate() != null); }, //------------------------------------------------------------------------- 'updateStatusWithValues': function(someValues) { var result; result = false; if (someValues['status'] != this.status()) { result = true; } this.setStatus(someValues['status']); this.setUsageDate(Clipperz.PM.Date.parseDateWithUTCFormat(someValues['requestDate'])); this.setConnectionInfo(someValues['connection']); return result; }, */ //------------------------------------------------------------------------- __syntaxFix__: "syntax fix" }); //############################################################################# Clipperz.PM.DataModel.OneTimePassword.computeKeyWithUsernameAndPassword = function(anUsername, aPassword) { return Clipperz.Crypto.SHA.sha_d256(new Clipperz.ByteArray(aPassword)).toHexString().substring(2); } Clipperz.PM.DataModel.OneTimePassword.computeKeyChecksumWithUsernameAndPassword = function(anUsername, aPassword) { return Clipperz.Crypto.SHA.sha_d256(new Clipperz.ByteArray(anUsername + aPassword)).toHexString().substring(2); } //============================================================================= Clipperz.PM.DataModel.OneTimePassword.isValidOneTimePasswordValue = function(aPassword) { var result; // "yaxx k7ww - f8y6 tqz5 - 58b6 th44 - 9cwv q0fg" -//console.log("Clipperz.PM.DataModel.OneTimePassword.isValidOneTimePasswordValue", aPassword); if (aPassword.replace(/[\s\-]/g, '').length == 32) { try { var passwordByteArray; passwordByteArray = new Clipperz.ByteArray(); passwordByteArray.appendBase32String(aPassword); result = true; } catch(exception) { result = false; } } else { result = false; } return result; } //============================================================================= Clipperz.PM.DataModel.OneTimePassword.normalizedOneTimePassword = function(aPassword) { var result; if (aPassword.replace(/[\s\-]/g, '').length == 32) { try { var passwordByteArray; passwordByteArray = new Clipperz.ByteArray(); passwordByteArray.appendBase32String(aPassword); result = passwordByteArray.toBase64String(); } catch(exception) { result = aPassword; } } else { result = aPassword; } -//console.log("Clipperz.PM.DataModel.OneTimePassword.normalizedOneTimePassword", aPassword, result); return result; } //############################################################################# diff --git a/frontend/gamma/js/Clipperz/PM/DataModel/Record.Version.Field.js b/frontend/gamma/js/Clipperz/PM/DataModel/Record.Version.Field.js index f51bbc2..986db40 100644 --- a/frontend/gamma/js/Clipperz/PM/DataModel/Record.Version.Field.js +++ b/frontend/gamma/js/Clipperz/PM/DataModel/Record.Version.Field.js @@ -1,164 +1,162 @@ /* -Copyright 2008-2011 Clipperz Srl +Copyright 2008-2013 Clipperz Srl -This file is part of Clipperz Community Edition. -Clipperz Community Edition is an online password manager. +This file is part of Clipperz, the online password manager. For further information about its features and functionalities please refer to http://www.clipperz.com. -* Clipperz Community Edition is free software: you can redistribute - it and/or modify it under the terms of the GNU Affero General Public - License as published by the Free Software Foundation, either version - 3 of the License, or (at your option) any later version. +* Clipperz is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. -* Clipperz Community Edition is distributed in the hope that it will - be useful, but WITHOUT ANY WARRANTY; without even the implied - warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* Clipperz is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. * You should have received a copy of the GNU Affero General Public - License along with Clipperz Community Edition. If not, see - <http://www.gnu.org/licenses/>. + License along with Clipperz. If not, see http://www.gnu.org/licenses/. */ try { if (typeof(Clipperz.PM.DataModel.Record.Version) == 'undefined') { throw ""; }} catch (e) { throw "Clipperz.PM.DataModel.Record.Version.Field depends on Clipperz.PM.DataModel.Record.Version!"; } Clipperz.PM.DataModel.Record.Version.Field = function(args) { Clipperz.PM.DataModel.Record.Version.Field.superclass.constructor.apply(this, arguments); this._recordVersion = args.recordVersion || Clipperz.Base.exception.raise('MandatoryParameter'); this._reference = args.reference || Clipperz.PM.Crypto.randomKey(); return this; } Clipperz.Base.extend(Clipperz.PM.DataModel.Record.Version.Field, Object, { 'toString': function() { return "Record.Version.Field (" + this.reference() + ")"; }, //------------------------------------------------------------------------- 'recordVersion': function () { return this._recordVersion; }, //------------------------------------------------------------------------- 'reference': function () { return this._reference; }, //------------------------------------------------------------------------- 'getItem': function (aKey) { return Clipperz.Async.callbacks("Clipperz.PM.DataModel.Record.Version.Field.getItem", [ MochiKit.Base.method(this, 'recordVersion'), MochiKit.Base.methodcaller('getValue', 'fields' + '.' + this.reference() + '.' + aKey) ], {trace:false}); }, 'setItem': function (aKey, aValue) { return Clipperz.Async.callbacks("Clipperz.PM.DataModel.Record.Version.Field.getItem", [ MochiKit.Base.method(this, 'recordVersion'), MochiKit.Base.methodcaller('setValue', 'fields' + '.' + this.reference() + '.' + aKey, aValue) ], {trace:false}); }, //------------------------------------------------------------------------- 'label': function () { return this.getItem('label'); }, 'setLabel': function (aValue) { return this.setItem('label', aValue); }, //------------------------------------------------------------------------- 'value': function () { return this.getItem('value'); }, 'setValue': function (aValue) { return this.setItem('value', aValue); }, //------------------------------------------------------------------------- 'actionType': function () { return Clipperz.Async.callbacks("Clipperz.PM.DataModel.Record.Version.Field.actionType", [ Clipperz.Async.collectResults("Clipperz.PM.DataModel.Record.Version.Field.actionType [collect results]", { 'isHidden': MochiKit.Base.method(this, 'isHidden'), 'value': MochiKit.Base.method(this, 'value') }, {trace:false}), function (someValues) { var result; // 'NONE', 'URL', 'EMAIL', 'PASSWORD' result = 'NONE'; if (someValues['isHidden']) { result = 'PASSWORD'; } else if (Clipperz.Base.isUrl(someValues['value'])) { result = 'URL' } else if (Clipperz.Base.isEmail(someValues['value'])) { result = 'EMAIL' }; return result; } ], {trace:false}); }, //------------------------------------------------------------------------- 'isHidden': function () { return this.getItem('hidden'); }, 'setIsHidden': function (aValue) { return this.setItem('hidden', aValue); }, //------------------------------------------------------------------------- 'isEmpty': function () { var deferredResult; deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.Record.Version.Field.isEmpty", {trace:false}); deferredResult.collectResults({ 'label': [ MochiKit.Base.method(this, 'label'), MochiKit.Base.partial(MochiKit.Base.operator.eq, '') ], 'value': [ MochiKit.Base.method(this, 'value'), MochiKit.Base.partial(MochiKit.Base.operator.eq, '') ], 'isHidden': [ MochiKit.Base.method(this, 'isHidden'), MochiKit.Base.partial(MochiKit.Base.operator.eq, false) ] }); deferredResult.addCallback(MochiKit.Base.values); deferredResult.addCallback(function(someValues) { return MochiKit.Iter.every(someValues, MochiKit.Base.operator.identity); }); deferredResult.callback(); return deferredResult; }, //------------------------------------------------------------------------- __syntaxFix__: "syntax fix" }); diff --git a/frontend/gamma/js/Clipperz/PM/DataModel/Record.Version.js b/frontend/gamma/js/Clipperz/PM/DataModel/Record.Version.js index dd35fc9..87b319c 100644 --- a/frontend/gamma/js/Clipperz/PM/DataModel/Record.Version.js +++ b/frontend/gamma/js/Clipperz/PM/DataModel/Record.Version.js @@ -1,333 +1,328 @@ /* -Copyright 2008-2011 Clipperz Srl +Copyright 2008-2013 Clipperz Srl -This file is part of Clipperz Community Edition. -Clipperz Community Edition is an online password manager. +This file is part of Clipperz, the online password manager. For further information about its features and functionalities please refer to http://www.clipperz.com. -* Clipperz Community Edition is free software: you can redistribute - it and/or modify it under the terms of the GNU Affero General Public - License as published by the Free Software Foundation, either version - 3 of the License, or (at your option) any later version. +* Clipperz is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. -* Clipperz Community Edition is distributed in the hope that it will - be useful, but WITHOUT ANY WARRANTY; without even the implied - warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* Clipperz is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. * You should have received a copy of the GNU Affero General Public - License along with Clipperz Community Edition. If not, see - <http://www.gnu.org/licenses/>. + License along with Clipperz. If not, see http://www.gnu.org/licenses/. */ try { if (typeof(Clipperz.PM.DataModel.Record) == 'undefined') { throw ""; }} catch (e) { throw "Clipperz.PM.DataModel.Record.Version depends on Clipperz.PM.DataModel.Record!"; } Clipperz.PM.DataModel.Record.Version = function(args) { -//console.log(">>> Record.new"); Clipperz.PM.DataModel.Record.Version.superclass.constructor.apply(this, arguments); this._getVersionFunction = args.getVersion || Clipperz.Base.exception.raise('MandatoryParameter'); this._fields = null; return this; } Clipperz.Base.extend(Clipperz.PM.DataModel.Record.Version, Clipperz.PM.DataModel.EncryptedRemoteObject, { 'toString': function() { return "Record.Version (" + this.reference() + ")"; }, //------------------------------------------------------------------------- 'reference': function () { return this._reference; }, //------------------------------------------------------------------------- /* 'hasPendingChanges': function () { var deferredResult; deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.Record.Version.hasPendingChanges", {trace:false}); deferredResult.addCallback(MochiKit.Base.bind(Clipperz.PM.DataModel.Record.Version.superclass.hasPendingChanges, this)); deferredResult.callback(); return deferredResult; }, */ //------------------------------------------------------------------------- 'hasPendingChangesWhenBrandNew': function () { var deferredResult; deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.Record.Version.hasPendingChangesWhenBrandNew", {trace:false}); deferredResult.addMethod(this, 'fields'); deferredResult.addCallback(MochiKit.Base.values); deferredResult.addCallback(MochiKit.Base.map, MochiKit.Base.methodcaller('isEmpty')) deferredResult.addCallback(Clipperz.Async.collectAll); deferredResult.addCallback(function(someValues) { return MochiKit.Iter.every(someValues, MochiKit.Base.operator.identity); }); deferredResult.addCallback(MochiKit.Base.operator.lognot) deferredResult.callback(); return deferredResult; }, //========================================================================= 'commitTransientState': function () { var deferredResult; deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.Record.Version.commitTransientState", {trace:false}); deferredResult.addCallback(MochiKit.Base.bind(Clipperz.PM.DataModel.Record.Version.superclass.commitTransientState, this)); deferredResult.callback(); return deferredResult; }, //========================================================================= 'unpackData': function (someData) { // ++ var result; -//console.log("Record.Version - UNPACK DATA", this, someData); result = someData; if ((someData['fields'] != null) && (someData['fields'] instanceof Array)) { var fields; var i,c; fields = someData['fields']; delete someData['fields']; someData['fields'] = {}; c = fields.length; for (i=0; i<c; i++) { someData['fields'][i] = fields[i]; } } return result; }, //========================================================================= 'fields': function () { var deferredResult; var deferredLock; deferredLock = this.getDeferredLockForKey('fields'); deferredResult = new Clipperz.Async.Deferred("Record.Version.fields", {trace:false}); deferredResult.acquireLock(deferredLock); deferredResult.addCallback(MochiKit.Base.bind(function () { var innerDeferredResult; if (this._fields == null) { innerDeferredResult = new Clipperz.Async.Deferred("Record.Version.fields <inner deferred>", {trace:false}); innerDeferredResult.addMethod(this, 'getValue', 'fields'); innerDeferredResult.addCallback(MochiKit.Base.bind(function (someObjectData) { var reference; this._fields = {}; for (reference in someObjectData) { var recordVersionField; recordVersionField = new Clipperz.PM.DataModel.Record.Version.Field({ 'recordVersion': this, 'reference': reference }); this._fields[reference] = recordVersionField; } return this._fields; }, this)); innerDeferredResult.callback(); } else { innerDeferredResult = MochiKit.Async.succeed(this._fields); } return innerDeferredResult; }, this)); deferredResult.releaseLock(deferredLock); deferredResult.callback(); return deferredResult; }, //------------------------------------------------------------------------- 'getFieldsValues': function () { return this.getValue('fields'); }, //------------------------------------------------------------------------- 'addField': function (someParameters) { var newField; newField = new Clipperz.PM.DataModel.Record.Version.Field({recordVersion:this}); return Clipperz.Async.callbacks("Record.Version.addField", [ MochiKit.Base.method(this, 'fields'), MochiKit.Base.method(this, '_getObjectDataStore'), MochiKit.Base.methodcaller('values'), Clipperz.Base.serializeJSON, MochiKit.Base.bind(function () { this._fields[newField.reference()] = newField; }, this), MochiKit.Base.method(newField, 'setLabel', someParameters['label']), MochiKit.Base.method(newField, 'setValue', someParameters['value']), MochiKit.Base.method(newField, 'setIsHidden', someParameters['isHidden']), MochiKit.Base.method(this, '_getObjectDataStore'), MochiKit.Base.methodcaller('values'), Clipperz.Base.serializeJSON, MochiKit.Base.partial(MochiKit.Async.succeed, newField) ], {trace:false}); }, //------------------------------------------------------------------------- 'removeField': function (aField) { return Clipperz.Async.callbacks("Record.Version.removeField", [ MochiKit.Base.method(this, 'fields'), MochiKit.Base.bind(function () { delete this._fields[aField.reference()]; }, this), MochiKit.Base.method(this, 'removeValue', 'fields' + '.' + aField.reference()) ], {trace:false}); }, //------------------------------------------------------------------------- /* 'sortFieldReference': function (someSortedFieldReferences) { }, */ //========================================================================= /* 'directLogins': function () { return MochiKit.Base.values(this._directLogins); }, 'addDirectLogin': function (aDirectLogin) { this._directLogins[aDirectLogin.reference()] = aDirectLogin; }, */ //========================================================================= /* 'updateValues': function (anotherVersion) { return Clipperz.Async.callbacks("Record.Version.updateValue", [ MochiKit.Base.partial(MochiKit.Async.succeed, this) ], {trace:false}); }, */ //========================================================================= 'setRemoteData': function (aValue) { this._remoteData = aValue; return aValue; }, //========================================================================= 'getVersionFunction': function () { return this._getVersionFunction; }, 'previousVersion': function () { return Clipperz.Async.callbacks("Record.Versions.previousVersion", [ MochiKit.Base.method(this, 'previousVersionReference'), this.getVersionFunction() ], {trace:false}); }, 'previousVersionReference': function () { return this.getValue('previousVersionReference'); }, 'previousVersionKey': function () { // TODO: this value i encrypted on its own. So it can not be saved in the main objectStore!!! return this.getValue('previousVersionKey'); }, //------------------------------------------------------------------------- 'setPreviousVersionReferenceAndKey': function (aVersionObjectAndKey) { // this._previousVersion = anotherVersion; return Clipperz.Async.callbacks("Record.Version.setPreviousVersion", [ MochiKit.Base.method(this, 'setValue', 'previousVersionReference', aVersionObjectAndKey['reference']), MochiKit.Base.method(this, 'setValue', 'previousVersionKey', aVersionObjectAndKey['key']) ], {trace:false}); }, //========================================================================= 'revertChanges': function () { this.setReference(this.transientState()['originalReference']); Clipperz.PM.DataModel.Record.Version.superclass.revertChanges.apply(this, arguments); }, //------------------------------------------------------------------------- 'prepareRemoteDataWithKey': function (aKey) { var deferredResult; var result; result = {}; -//console.log("prepareRemoteDataWithKey", aKey); deferredResult = new Clipperz.Async.Deferred("Record.Version.prepareRemoteDataWithKey", {trace:false}); if (this.isBrandNew() == false) { this.transientState()['originalReference'] = this.reference(); deferredResult.collectResults({ 'key': MochiKit.Base.partial(MochiKit.Async.succeed, aKey), 'value': MochiKit.Base.method(this, 'getKey'), 'version': MochiKit.Base.partial(MochiKit.Async.succeed, Clipperz.PM.Crypto.encryptingFunctions.currentVersion) }); deferredResult.addCallback(Clipperz.PM.Crypto.deferredEncrypt); deferredResult.addCallback(Clipperz.Async.setItem, result, 'previousVersionKey'); } else { deferredResult.addCallback(Clipperz.Async.setItem, result, 'previousVersionKey', Clipperz.PM.Crypto.nullValue); } deferredResult.addCallback(MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.prepareRemoteDataWithKey, this, aKey)); deferredResult.addCallback(MochiKit.Base.update, result); deferredResult.addMethod(this, 'setRemoteData'); deferredResult.callback(); return deferredResult; }, //========================================================================= /* 'deleteAllCleanTextData': function () { return Clipperz.PM.DataModel.Record.Version.superclass.deleteAllCleanTextData.apply(this, arguments); }, 'hasAnyCleanTextData': function () { return Clipperz.PM.DataModel.Record.Version.superclass.hasAnyCleanTextData.apply(this, arguments); }, */ //========================================================================= __syntaxFix__: "syntax fix" }); diff --git a/frontend/gamma/js/Clipperz/PM/DataModel/Record.js b/frontend/gamma/js/Clipperz/PM/DataModel/Record.js index b816f80..3fc1813 100644 --- a/frontend/gamma/js/Clipperz/PM/DataModel/Record.js +++ b/frontend/gamma/js/Clipperz/PM/DataModel/Record.js @@ -1,878 +1,854 @@ /* -Copyright 2008-2011 Clipperz Srl +Copyright 2008-2013 Clipperz Srl -This file is part of Clipperz Community Edition. -Clipperz Community Edition is an online password manager. +This file is part of Clipperz, the online password manager. For further information about its features and functionalities please refer to http://www.clipperz.com. -* Clipperz Community Edition is free software: you can redistribute - it and/or modify it under the terms of the GNU Affero General Public - License as published by the Free Software Foundation, either version - 3 of the License, or (at your option) any later version. +* Clipperz is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. -* Clipperz Community Edition is distributed in the hope that it will - be useful, but WITHOUT ANY WARRANTY; without even the implied - warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* Clipperz is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. * You should have received a copy of the GNU Affero General Public - License along with Clipperz Community Edition. If not, see - <http://www.gnu.org/licenses/>. + License along with Clipperz. If not, see http://www.gnu.org/licenses/. */ if (typeof(Clipperz) == 'undefined') { Clipperz = {}; } if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; } if (typeof(Clipperz.PM.DataModel) == 'undefined') { Clipperz.PM.DataModel = {}; } Clipperz.PM.DataModel.Record = function(args) { -//console.log(">>> new Clipperz.PM.DataModel.Record", args); Clipperz.PM.DataModel.Record.superclass.constructor.apply(this, arguments); this._updateDate = (args.updateDate ? Clipperz.PM.Date.parse(args.updateDate) : Clipperz.Base.exception.raise('MandatoryParameter')); this._retrieveIndexDataFunction = args.retrieveIndexDataFunction || Clipperz.Base.exception.raise('MandatoryParameter'); this._updateIndexDataFunction = args.updateIndexDataFunction || Clipperz.Base.exception.raise('MandatoryParameter'); this._retrieveDirectLoginIndexDataFunction = args.retrieveDirectLoginIndexDataFunction || null; this._setDirectLoginIndexDataFunction = args.setDirectLoginIndexDataFunction || null; this._removeDirectLoginIndexDataFunction = args.removeDirectLoginIndexDataFunction || null; this._createNewDirectLoginFunction = args.createNewDirectLoginFunction || null; this._directLogins = {}; this._versions = {}; this._currentRecordVersion = null; if (this.isBrandNew()) { var newVersion; this.setNotes(''); newVersion = new Clipperz.PM.DataModel.Record.Version({ 'retrieveKeyFunction': MochiKit.Base.method(this, 'getVersionKey'), 'getVersion': MochiKit.Base.method(this, 'getVersion') }); this._versions[newVersion.reference()] = newVersion; this._currentVersionReference = newVersion.reference(); // this.setLabel(''); } -//console.log("<<< new Clipperz.PM.DataModel.Record", args); - return this; } Clipperz.Base.extend(Clipperz.PM.DataModel.Record, Clipperz.PM.DataModel.EncryptedRemoteObject, { 'toString': function() { return "Record (" + this.reference() + ")"; }, //------------------------------------------------------------------------- 'reference': function () { return this._reference; }, //========================================================================= 'getIndexData': function () { return this._retrieveIndexDataFunction(this.reference()); }, //......................................................................... 'getIndexDataForKey': function (aKey) { return Clipperz.Async.callbacks("Record.getIndexDataForKey", [ MochiKit.Base.method(this, 'getIndexData'), MochiKit.Base.itemgetter(aKey) ], {trace:false}); }, //------------------------------------------------------------------------- 'setIndexDataForKey': function (aKey, aValue) { // return this._updateIndexDataFunction(this.reference(), aKey, aValue); var deferredResult; deferredResult = new Clipperz.Async.Deferred("Record.setIndexDataForKey", {trace:false}); deferredResult.addMethod(this, 'getIndexDataForKey', aKey); deferredResult.addCallback(MochiKit.Base.bind(function (aCurrentValue) { var result; var originalValue; originalValue = this.transientState().getValue('originalValues.indexData.' + aKey); if (originalValue == null) { originalValue = this.transientState().setValue('originalValues.indexData.' + aKey, aCurrentValue); } if (aCurrentValue != aValue) { if (originalValue != aValue) { this.transientState().setValue('hasPendingChanges.indexData.' + aKey, true); } else { this.transientState().setValue('hasPendingChanges.indexData.' + aKey, false); } result = this._updateIndexDataFunction(this.reference(), aKey, aValue); } else { result = MochiKit.Async.succeed(aValue); } return result; }, this)); deferredResult.callback(); return deferredResult; }, //========================================================================= /* 'key': function () { return this.getIndexDataForKey('key'); }, */ //========================================================================= 'label': function () { return this.getIndexDataForKey('label'); }, //......................................................................... 'setLabel': function (aValue) { return this.setIndexDataForKey('label', aValue); }, //========================================================================= 'headerNotes': function () { return this.getIndexDataForKey('notes'); }, //------------------------------------------------------------------------- 'notes': function () { return Clipperz.Async.callbacks("Record.notes", [ MochiKit.Base.method(this, 'headerNotes'), MochiKit.Base.bind(function (someHeaderNotes) { var result; if ((someHeaderNotes == null) || (typeof(someHeaderNotes) == 'undefined')) { result = this.getValue('notes'); } else { result = MochiKit.Async.succeed(someHeaderNotes); } return result; }, this) ], {trace:false}); }, //......................................................................... 'setNotes': function (aValue) { return this.setValue('notes', aValue); }, //========================================================================= 'updateDate': function () { return MochiKit.Async.succeed(this._updateDate); }, //========================================================================= 'favicon': function () { var result; var directLogins; directLogins = MochiKit.Base.values(this.directLogins()); if (directLogins.length > 0) { result = directLogins[0].favicon(); // } else if (/* is there an URL to use for searching a favicon */){ } else { result = null; // MochiKit.Async.succeed(Clipperz.PM.Strings['defaultFaviconUrl']); } return result; }, //------------------------------------------------------------------------- 'searchableContent': function () { var deferredResult; -//console.log(">>> searchableContent"); deferredResult = new Clipperz.Async.Deferred("Record.searchableContent", {trace:false}); deferredResult.collectResults({ 'recordLabel': MochiKit.Base.method(this, 'label'), 'directLoginLabels': [ MochiKit.Base.method(this, 'directLoginReferences'), MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.itemgetter('label')) ] }) deferredResult.addCallback(function (someValues) { return someValues['recordLabel'] + ' ' + someValues['directLoginLabels'].join(' '); }); deferredResult.callback(); -//console.log("<<< searchableContent"); return deferredResult; }, //------------------------------------------------------------------------- 'isMatching': function (aRegExp) { return Clipperz.Async.callbacks("deferredFilterFunction", [ MochiKit.Base.method(this, 'searchableContent'), MochiKit.Base.method(aRegExp, 'test'), function (doesItMatch) { var result; if (doesItMatch) { result = MochiKit.Async.succeed('match'); } else { result = MochiKit.Async.fail('miss'); } return result; } ], {trace:false}); }, //========================================================================= 'directLogins': function () { return this._directLogins; }, 'addDirectLogin': function (aDirectLogin) { this._directLogins[aDirectLogin.reference()] = aDirectLogin; }, 'directLoginWithReference': function (aDirectLoginReference) { return this._directLogins[aDirectLoginReference]; }, 'createNewDirectLoginFunction': function () { return this._createNewDirectLoginFunction; }, 'saveOriginalDirectLoginStatusToTransientState': function () { if (this.transientState().getValue('directLogins') == null) { // this.transientState().setValue('directLogins', this._directLogins) -//console.log("SET TRANSIENT STATE", Clipperz.Base.serializeJSON(MochiKit.Base.keys(this.transientState().getValue('directLogins')))) MochiKit.Iter.forEach(MochiKit.Base.keys(this._directLogins), MochiKit.Base.bind(function(aKey) { this.transientState().setValue('directLogins' + '.' + aKey, this._directLogins[aKey]) }, this)) } }, 'createNewDirectLogin': function () { this.saveOriginalDirectLoginStatusToTransientState(); return this.createNewDirectLoginFunction()(this); }, 'removeDirectLogin': function(aDirectLogin) { this.saveOriginalDirectLoginStatusToTransientState(); return Clipperz.Async.callbacks("Record.removeDirectLogin", [ MochiKit.Base.method(this, 'removeValue', 'directLogins' + '.' + aDirectLogin.reference()), MochiKit.Base.bind(function () { delete this._directLogins[aDirectLogin.reference()] }, this) ], {trace:false}); }, 'directLoginReferences': function () { var result; result = Clipperz.Async.callbacks("Record.directLoginReferences", [ MochiKit.Base.method(this, 'directLogins'), MochiKit.Base.values, function (someDirectLogins) { var result; var i,c; result = []; c = someDirectLogins.length; for (i=0; i<c; i++) { result.push(Clipperz.Async.collectResults("Record.directLoginReferences - collectResults", { '_rowObject': MochiKit.Async.succeed, '_reference': MochiKit.Base.methodcaller('reference'), 'label': MochiKit.Base.methodcaller('label'), 'favicon': MochiKit.Base.methodcaller('favicon') }, {trace:false})(someDirectLogins[i])); }; return result; }, Clipperz.Async.collectAll ], {trace:false}); return result; }, //========================================================================= 'unpackRemoteData': function (someData) { var result; -//console.log("new Clipperz.PM.DataModel.Record.Version [2]"); /* this._currentRecordVersion = new Clipperz.PM.DataModel.Record.Version({ 'reference': someData['currentVersion']['reference'], 'retrieveKeyFunction': MochiKit.Base.method(this, 'getCurrentRecordVersionKey'), 'remoteData': someData['currentVersion'], }); */ var versionKey; for (versionKey in someData['versions']) { -//console.log("### versionKey", versionKey); this._versions[versionKey] = new Clipperz.PM.DataModel.Record.Version({ 'reference': versionKey, 'retrieveKeyFunction': MochiKit.Base.method(this, 'getVersionKey'), 'remoteData': someData['versions'][versionKey], 'getVersion': MochiKit.Base.method(this, 'getVersion') }) } // this._currentVersionReference = someData['currentVersion']['reference']; this._currentVersionReference = someData['currentVersion']; -//console.log("=== currentVersionReference", this._currentVersionReference, someData); result = Clipperz.PM.DataModel.Record.superclass.unpackRemoteData.apply(this, arguments); return result; }, //------------------------------------------------------------------------- 'unpackData': function (someData) { var result; result = Clipperz.PM.DataModel.Record.superclass.unpackData.apply(this, arguments); if (MochiKit.Base.isUndefinedOrNull(result['notes'])) { result['notes'] = '' } return result; }, //------------------------------------------------------------------------- 'prepareRemoteDataWithKey': function (aKey) { var deferredResult; var newVersionKey; var result; newVersionKey = Clipperz.PM.Crypto.randomKey(); result = {}; deferredResult = new Clipperz.Async.Deferred("Record.prepareRemoteDataWithKey", {trace:false}); deferredResult.addCallbackList([ Clipperz.Async.collectResults("Record.prepareRemoteDataWithKey - collect results", { 'isBrandNew': MochiKit.Base.method(this, 'isBrandNew'), 'versionHasPendingChanges': [ // MochiKit.Base.method(this, 'getCurrentRecordVersion'), // MochiKit.Base.methodcaller('hasPendingChanges') MochiKit.Base.method(this, 'invokeCurrentRecordVersionMethod', 'hasPendingChanges') ] }), Clipperz.Async.or, Clipperz.Async.deferredIf("Current Version has pending changes", [ MochiKit.Base.method(this, 'createNewRecordVersion'), MochiKit.Base.methodcaller('prepareRemoteDataWithKey', newVersionKey), MochiKit.Base.partial(Clipperz.Async.setItem, result, 'currentRecordVersion'), MochiKit.Base.method(this, 'setCurrentRecordVersionKey', newVersionKey) ], []), MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.prepareRemoteDataWithKey, this, aKey), MochiKit.Base.partial(Clipperz.Async.setItem, result, 'record'), MochiKit.Base.partial(MochiKit.Async.succeed, result) ]); deferredResult.callback(); return deferredResult; }, //========================================================================= 'fields': function () { return this.invokeCurrentRecordVersionMethod('fields'); }, 'addField': function (someParameters) { return this.invokeCurrentRecordVersionMethod('addField', someParameters); }, 'removeField': function (someParameters) { return this.invokeCurrentRecordVersionMethod('removeField', someParameters); }, // 'sortFieldReference': function (someSortedFieldReferences) { // return this.invokeCurrentRecordVersionMethod('sortFieldReference', someSortedFieldReferences); // }, 'getFieldsValues': function () { return this.invokeCurrentRecordVersionMethod('getFieldsValues'); }, 'fieldWithLabel': function (aLabel) { return Clipperz.Async.callbacks("Record.fieldWithLabel", [ MochiKit.Base.method(this, 'fields'), MochiKit.Base.values, MochiKit.Base.partial(Clipperz.Async.deferredFilter, function (aField) { return Clipperz.Async.callbacks("Record.fieldWithLabel - check field label", [ MochiKit.Base.methodcaller('label'), MochiKit.Base.partial(MochiKit.Base.operator.eq, aLabel) ], {trace:false}, aField); }), function (someFilteredResults) { var result; switch (someFilteredResults.length) { case 0: result = null; break; case 1: result = someFilteredResults[0]; break; default: WTF = TODO; break; } return result; } ], {trace:false}); }, //========================================================================= 'getVersion': function (aVersionReference) { return Clipperz.Async.callbacks("Record.getVersion", [ MochiKit.Base.method(this, 'getVersions'), MochiKit.Base.itemgetter(aVersionReference) ], {trace:false}); }, //------------------------------------------------------------------------- 'getVersionKey': function (aVersionReference) { var deferredResult; var transientStateKey; transientStateKey = 'versionKeys' + '.' + aVersionReference; if (this.transientState().getValue(transientStateKey) != null) { deferredResult = MochiKit.Async.succeed(this.transientState().getValue(transientStateKey)); } else { deferredResult = Clipperz.Async.callbacks("Record.getVersionKey", [ MochiKit.Base.method(this, 'getVersions'), MochiKit.Base.partial(MochiKit.Base.operator.eq, aVersionReference, this.currentVersionReference()), Clipperz.Async.deferredIf("getVersionKey for current version", [ MochiKit.Base.method(this, 'getCurrentRecordVersionKey'), MochiKit.Base.method(this.transientState(), 'setValue', transientStateKey) ],[ MochiKit.Async.fail ]) ], {trace:false}); } return deferredResult; }, //------------------------------------------------------------------------- 'versions': function () { return this._versions; }, 'getVersions': function () { return Clipperz.Async.callbacks("Record.versions", [ MochiKit.Base.method(this, 'getValue', 'fakeKey, just to trigger unpackRemoteData'), MochiKit.Base.bind(function () { return this._versions; }, this) ], {trace:false}); }, //------------------------------------------------------------------------- 'getCurrentRecordVersion': function () { return Clipperz.Async.callbacks("Record.getCurrentRecordVersion", [ // MochiKit.Base.method(this, 'getValue', 'fakeKey, just to trigger unpackRemoteData'), // MochiKit.Base.bind(function () { return this._currentRecordVersion; }, this) MochiKit.Base.method(this, 'versions'), MochiKit.Base.itemgetter(this.currentVersionReference()), Clipperz.Async.deferredIf("The current version is available", [ MochiKit.Async.succeed ], [ MochiKit.Base.method(this, 'getVersions'), MochiKit.Base.bind(function (someVersions) { return someVersions[this.currentVersionReference()]}, this) ]) ], {trace:false}); }, 'setCurrentRecordVersion': function (aRecordVersion) { this._currentVersionReference = aRecordVersion.reference(); }, //......................................................................... 'currentVersionReference': function () { -//console.log("currentVersionReference"); return this._currentVersionReference; }, //------------------------------------------------------------------------- 'createNewRecordVersion': function () { var deferredResult; if (this.isBrandNew()) { deferredResult = this.getCurrentRecordVersion(); } else { var newVersion; newVersion = new Clipperz.PM.DataModel.Record.Version({ // 'reference': versionKey, 'retrieveKeyFunction': MochiKit.Base.method(this, 'getVersionKey'), // 'remoteData': {}, 'getVersion': MochiKit.Base.method(this, 'getVersion') }) this._versions[newVersion.reference()] = newVersion; deferredResult = Clipperz.Async.callbacks("Record.createNewRecordVersion", [ // MochiKit.Base.method(this, 'getCurrentRecordVersion'), // MochiKit.Base.methodcaller('values'), MochiKit.Base.method(this, 'invokeCurrentRecordVersionMethod', 'values'), MochiKit.Base.method(newVersion, 'setValues'), Clipperz.Async.collectResults("Record.createNewRecordVersion [collect results]", { 'reference': MochiKit.Base.method(this, 'currentVersionReference'), 'key': MochiKit.Base.method(this, 'getCurrentRecordVersionKey') }, {trace:false}), MochiKit.Base.method(newVersion, 'setPreviousVersionReferenceAndKey'), // MochiKit.Base.method(this, 'getCurrentRecordVersion'), // MochiKit.Base.method(this, 'revertChanges'), MochiKit.Base.method(this, 'invokeCurrentRecordVersionMethod', 'revertChanges'), MochiKit.Base.method(this, 'setCurrentRecordVersion', newVersion), MochiKit.Base.partial(MochiKit.Async.succeed, newVersion) ], {trace:false}); } return deferredResult; }, //------------------------------------------------------------------------- 'getCurrentRecordVersionKey': function () { -//console.log("getCurrentRecordVersionKey"); return Clipperz.Async.callbacks("Record.getCurrentRecordVersionKey", [ MochiKit.Base.method(this, 'getValue', 'currentVersionKey'), Clipperz.Async.deferredIf("currentVersionKey is NOT null", [ MochiKit.Async.succeed ], [ MochiKit.Base.method(this, 'getKey') ]) ], {trace:false}); }, 'setCurrentRecordVersionKey': function (aValue) { // TODO: triple check this method! return Clipperz.Async.callbacks("Record.setCurrentRecordVersionKey", [ MochiKit.Base.method(this, 'setValue', 'currentVersionKey', aValue) ], {trace:false}); }, //------------------------------------------------------------------------- 'invokeCurrentRecordVersionMethod': function (aMethodName, someValues) { -//console.log(">>> invokeCurrentRecordVersionMethod", aMethodName); return Clipperz.Async.callbacks("Record.invokeCurrentRecordVersionMethod", [ MochiKit.Base.method(this, 'getCurrentRecordVersion'), -//function (aValue) { console.log("=== getCurrentRecordVersion", aValue); return aValue}, MochiKit.Base.methodcaller(aMethodName, someValues) ], {trace:false}); }, 'lazilyinvokeCurrentRecordVersionMethod': function (aMethodName, someValues, defaultResult) { return Clipperz.Async.callbacks("Record.lazilyinvokeCurrentRecordVersionMethod", [ MochiKit.Base.method(this, 'currentVersionReference'), -//function (aValue) { console.log("LAZY -> versions", aValue); return aValue; }, Clipperz.Async.deferredIf("versions has been loaded", [ -//function (aValue) { console.log("LAZY -> then"); return aValue; }, MochiKit.Base.method(this, 'getCurrentRecordVersion'), MochiKit.Base.methodcaller(aMethodName, someValues), -//function (aValue) { console.log("LAZY <- then"); return aValue; } ], [ -//function (aValue) { console.log("LAZY -> else"); return aValue; }, MochiKit.Base.partial(MochiKit.Async.succeed, defaultResult), -//function (aValue) { console.log("LAZY <- else"); return aValue; } ]) ], {trace:false}); }, //========================================================================= 'hasPendingChanges': function () { var deferredResult; if (this.hasInitiatedObjectDataStore()) { deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.Record.hasPendingChanges", {trace:false}); deferredResult.collectResults({ 'super': MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.hasPendingChanges, this), 'currentVersion': [ // MochiKit.Base.method(this, 'getCurrentRecordVersion'), // MochiKit.Base.methodcaller('hasPendingChanges') MochiKit.Base.method(this, 'invokeCurrentRecordVersionMethod', 'hasPendingChanges') ], 'directLogins': [ MochiKit.Base.method(this, 'directLogins'), -//function (aValue) { console.log("Record.directLogins", aValue); return aValue; }, MochiKit.Base.values, MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('hasPendingChanges')), Clipperz.Async.collectAll, Clipperz.Async.or // function(someValues) { // return MochiKit.Iter.some(someValues, MochiKit.Base.operator.identity); // } ] }); -//deferredResult.addCallback(function (aValue) { console.log("Record.hasPendingResults", aValue); return aValue; }); deferredResult.addCallback(MochiKit.Base.values); deferredResult.addCallback(MochiKit.Base.bind(function(someValues) { var result; result = MochiKit.Iter.some(someValues, MochiKit.Base.operator.identity); if ((result == false) && (this.isBrandNew() == false)) { result = MochiKit.Iter.some(MochiKit.Base.values(this.transientState().getValue('hasPendingChanges.indexData')), MochiKit.Base.operator.identity); } return result; }, this)); deferredResult.callback(); } else { deferredResult = Clipperz.Async.callbacks("Recrod.hasPendingChanges [hasInitiatedObjectDataStore == false]", [ MochiKit.Base.method(this, 'directLogins'), MochiKit.Base.values, MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('hasPendingChanges')), Clipperz.Async.collectAll, Clipperz.Async.or // function(someValues) { // return MochiKit.Iter.some(someValues, MochiKit.Base.operator.identity); // } ], {trace:false}) } return deferredResult; }, //------------------------------------------------------------------------- 'hasPendingChangesWhenBrandNew': function () { var deferredResult; deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.Record.hasPendingChangesWhenBrandNew", {trace:false}); deferredResult.collectResults({ 'label': [ MochiKit.Base.method(this, 'label'), MochiKit.Base.partial(MochiKit.Base.operator.ne, '') ], 'notes': [ MochiKit.Base.method(this, 'notes'), MochiKit.Base.partial(MochiKit.Base.operator.ne, '') ] }); // deferredResult.addCallback(MochiKit.Base.values); // deferredResult.addCallback(function(someValues) { // return MochiKit.Iter.some(someValues, MochiKit.Base.operator.identity); // }); deferredResult.addCallback(Clipperz.Async.or); deferredResult.callback(); return deferredResult; }, //------------------------------------------------------------------------- 'isBrandNewWithNoPendingChanges': function () { var deferredResult; if (this.isBrandNew() == false) { deferredResult = MochiKit.Async.succeed(false); } else { deferredResult = Clipperz.Async.callbacks("Record.isBrandNewWithNoPendingChanges", [ MochiKit.Base.method(this, 'hasPendingChanges'), MochiKit.Base.operator.lognot ], {trace:false}); } return deferredResult; }, //========================================================================= 'revertChanges': function () { var deferredResult; if (this.isBrandNew() == false) { deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.Record.revertChanges", {trace:false}); deferredResult.addMethod(this, 'hasPendingChanges'); deferredResult.addIf([ // MochiKit.Base.method(this, 'getCurrentRecordVersion'), // MochiKit.Base.methodcaller('revertChanges'), MochiKit.Base.method(this,'invokeCurrentRecordVersionMethod', 'revertChanges'), MochiKit.Base.method(this, 'directLogins'), MochiKit.Base.values, MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('revertChanges')), MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.revertChanges, this) ], [ MochiKit.Async.succeed ]); deferredResult.callback(); } else { // this.deleteAllCleanTextData(); deferredResult = MochiKit.Async.succeed(); } return deferredResult; }, //------------------------------------------------------------------------- 'resetTransientState': function (isCommitting) { // if ((isCommitting == false) && (this.transientState().getValue('directLogins') != null)) { // this._directLogins = this.transientState().getValue('directLogins'); // } return Clipperz.Async.callbacks("Record.resetTransientState", [ //- MochiKit.Base.method(this, 'getCurrentRecordVersion'), //- MochiKit.Base.methodcaller('resetTransientState'), // MochiKit.Base.method(this, 'invokeCurrentRecordVersionMethod', 'resetTransientState'), MochiKit.Base.method(this, 'lazilyinvokeCurrentRecordVersionMethod', 'resetTransientState'), MochiKit.Base.method(this, 'directLogins'), -//function (aValue) { console.log("resetTransientState - directLogins", aValue); return aValue; }, MochiKit.Base.values, MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('resetTransientState')), MochiKit.Base.bind(function () { if ((isCommitting == false) && (this.transientState().getValue('directLogins') != null)) { this._directLogins = this.transientState().getValue('directLogins'); } }, this), MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.resetTransientState, this, isCommitting) ], {trace:false}) }, //------------------------------------------------------------------------- 'commitTransientState': function () { var deferredResult; deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.Record.commitTransientState", {trace:false}); deferredResult.addMethod(this, 'hasPendingChanges'); deferredResult.addIf([ MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.commitTransientState, this), // MochiKit.Base.method(this, 'getCurrentRecordVersion'), // MochiKit.Base.methodcaller('commitTransientState'), MochiKit.Base.method(this, 'invokeCurrentRecordVersionMethod', 'commitTransientState'), MochiKit.Base.method(this, 'directLogins'), MochiKit.Base.values, MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('commitTransientState')) ], [ MochiKit.Async.succeed ]); deferredResult.callback(); return deferredResult; }, //========================================================================= 'retrieveDirectLoginIndexDataFunction': function () { -//console.log("Record.retrieveDirectLoginIndexDataFunction", this._retrieveDirectLoginIndexDataFunction); return this._retrieveDirectLoginIndexDataFunction; }, 'setDirectLoginIndexDataFunction': function () { return this._setDirectLoginIndexDataFunction; }, 'removeDirectLoginIndexDataFunction': function () { return this._removeDirectLoginIndexDataFunction; }, //========================================================================= 'deleteAllCleanTextData': function () { // return Clipperz.PM.DataModel.Record.superclass.deleteAllCleanTextData.apply(this, arguments); return Clipperz.Async.callbacks("Record.deleteAllCleanTextData", [ MochiKit.Base.method(this, 'versions'), MochiKit.Base.values, MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('deleteAllCleanTextData')), MochiKit.Base.method(this, 'directLogins'), MochiKit.Base.values, MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('deleteAllCleanTextData')), MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.deleteAllCleanTextData, this) ], {trace:false}); }, 'hasAnyCleanTextData': function () { // return Clipperz.PM.DataModel.Record.superclass.hasAnyCleanTextData.apply(this, arguments); return Clipperz.Async.callbacks("Record.hasAnyCleanTextData", [ Clipperz.Async.collectResults("Record.hasAnyCleanTextData [collect results]", { 'versions': [ MochiKit.Base.method(this, 'versions'), MochiKit.Base.values, MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('hasAnyCleanTextData')), Clipperz.Async.collectAll ], 'directLogins': [ MochiKit.Base.method(this, 'directLogins'), MochiKit.Base.values, MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('hasAnyCleanTextData')), Clipperz.Async.collectAll ], 'super': [ MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.hasAnyCleanTextData, this) ] }, {trace:false}), Clipperz.Async.or ]) }, //========================================================================= __syntaxFix__: "syntax fix" }); diff --git a/frontend/gamma/js/Clipperz/PM/DataModel/User.Header.Legacy.js b/frontend/gamma/js/Clipperz/PM/DataModel/User.Header.Legacy.js index d6202ff..cda5a41 100644 --- a/frontend/gamma/js/Clipperz/PM/DataModel/User.Header.Legacy.js +++ b/frontend/gamma/js/Clipperz/PM/DataModel/User.Header.Legacy.js @@ -1,184 +1,182 @@ /* -Copyright 2008-2011 Clipperz Srl +Copyright 2008-2013 Clipperz Srl -This file is part of Clipperz Community Edition. -Clipperz Community Edition is an online password manager. +This file is part of Clipperz, the online password manager. For further information about its features and functionalities please refer to http://www.clipperz.com. -* Clipperz Community Edition is free software: you can redistribute - it and/or modify it under the terms of the GNU Affero General Public - License as published by the Free Software Foundation, either version - 3 of the License, or (at your option) any later version. +* Clipperz is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. -* Clipperz Community Edition is distributed in the hope that it will - be useful, but WITHOUT ANY WARRANTY; without even the implied - warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* Clipperz is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. * You should have received a copy of the GNU Affero General Public - License along with Clipperz Community Edition. If not, see - <http://www.gnu.org/licenses/>. + License along with Clipperz. If not, see http://www.gnu.org/licenses/. */ try { if (typeof(Clipperz.PM.DataModel.User) == 'undefined') { throw ""; }} catch (e) { throw "Clipperz.PM.DataModel.User.Header.Legacy depends on Clipperz.PM.DataModel.User!"; } if (typeof(Clipperz.PM.DataModel.User.Header) == 'undefined') { Clipperz.PM.DataModel.User.Header = {}; } Clipperz.PM.DataModel.User.Header.Legacy = function(args) { // args = args || {}; Clipperz.PM.DataModel.User.Header.Legacy.superclass.constructor.apply(this, arguments); this._retrieveRecordDetailFunction = args.retrieveRecordDetailFunction || Clipperz.Base.exception.raise('MandatoryParameter'); this._records = null; // this._directLogins = null; return this; } Clipperz.Base.extend(Clipperz.PM.DataModel.User.Header.Legacy, Clipperz.PM.DataModel.EncryptedRemoteObject, { 'toString': function() { return "Clipperz.PM.DataModel.User.Header.Legacy"; }, //------------------------------------------------------------------------- 'retrieveRecordDetailFunction': function () { return this._retrieveRecordDetailFunction; }, //------------------------------------------------------------------------- 'getRecordKey': function (aRecordReference) { var deferredResult; deferredResult = new Clipperz.Async.Deferred("User.Header.Legacy.getRecordKey", {trace:false}); deferredResult.addMethod(this, 'getRecordIndexData'); deferredResult.addCallback(MochiKit.Base.itemgetter('key')) deferredResult.callback(); return deferredResult; }, //========================================================================= 'getRecordIndexData': function (aRecordReference) { return this.getValue('records.' + aRecordReference); }, 'updateRecordIndexData': function (aRecordReference, aKey, aValue) { return this.setValue('records.' + aRecordReference + "." + aKey, aValue); }, //------------------------------------------------------------------------- 'getDirectLoginIndexData': function (aDirectLoginReference) { return this.getValue('directLogins.' + aDirectLoginReference); }, 'setDirectLoginIndexData': function (aDirectLoginReference, aKey, aValue) { return this.setValue('directLogins.' + aDirectLoginReference + '.' + aKey, aValue); }, 'removeDirectLoginIndexData': function (aDirectLoginReference) { return this.removeValue('directLogins.' + aDirectLoginReference); }, //========================================================================= 'records': function () { var deferredResult; var deferredLock; deferredLock = this.getDeferredLockForKey('records'); deferredResult = new Clipperz.Async.Deferred("User.Header.Legacy.records", {trace:false}); deferredResult.acquireLock(deferredLock); deferredResult.addCallback(MochiKit.Base.bind(function () { var innerDeferredResult; if (this._records == null) { innerDeferredResult = new Clipperz.Async.Deferred("User.Header.Legacy.records <inner deferred>", {trace:false}); innerDeferredResult.collectResults({ 'header': [ // MochiKit.Base.method(this, 'getObjectDataStore'), // MochiKit.Base.methodcaller('values') MochiKit.Base.method(this, 'values') ], 'recordsStats': [ MochiKit.Base.method(this, 'getRemoteData'), MochiKit.Base.itemgetter('recordsStats') ] }); innerDeferredResult.addCallback(MochiKit.Base.bind(function (someObjectData) { var reference; this._records = {}; // this._directLogins = {}; for (reference in someObjectData['header']['records']) { var record; record = new Clipperz.PM.DataModel.Record({ 'reference': reference, 'retrieveKeyFunction': MochiKit.Base.method(this, 'getRecordKey'), 'retrieveRemoteDataFunction': this.retrieveRecordDetailFunction(), // 'encryptedDataKeypath': 'data', // 'encryptedVersionKeypath': 'version', 'retrieveIndexDataFunction': MochiKit.Base.method(this, 'getRecordIndexData'), 'updateIndexDataFunction': MochiKit.Base.method(this, 'updateRecordIndexData'), 'updateDate': someObjectData['recordsStats'][reference]['updateDate'], 'retrieveDirectLoginIndexDataFunction': MochiKit.Base.method(this, 'getDirectLoginIndexData'), 'setDirectLoginIndexDataFunction': MochiKit.Base.method(this, 'setDirectLoginIndexData'), 'removeDirectLoginIndexDataFunction': MochiKit.Base.method(this, 'removeDirectLoginIndexData') }); this._records[reference] = record; } for (reference in someObjectData['header']['directLogins']) { var directLogin; var record; record = this._records[someObjectData['header']['directLogins'][reference]['record']]; if (record != null) { directLogin = new Clipperz.PM.DataModel.DirectLogin({ 'reference': reference, 'record': record //, // 'retrieveIndexDataFunction': MochiKit.Base.method(this, 'getDirectLoginIndexData'), // 'setIndexDataFunction': MochiKit.Base.method(this, 'setDirectLoginIndexData'), // 'removeIndexDataFunction': MochiKit.Base.method(this, 'removeDirectLoginIndexData') }); } else { Clipperz.log("WARNING: DIRECT LOGIN without a matching RECORD!!"); } } return this._records; }, this)); innerDeferredResult.callback(); } else { innerDeferredResult = MochiKit.Async.succeed(this._records); } return innerDeferredResult; }, this)); deferredResult.releaseLock(deferredLock); deferredResult.callback(); return deferredResult; }, //========================================================================= __syntaxFix__: "syntax fix" }); diff --git a/frontend/gamma/js/Clipperz/PM/DataModel/User.Header.OneTimePasswords.js b/frontend/gamma/js/Clipperz/PM/DataModel/User.Header.OneTimePasswords.js index 3528db6..e82da47 100644 --- a/frontend/gamma/js/Clipperz/PM/DataModel/User.Header.OneTimePasswords.js +++ b/frontend/gamma/js/Clipperz/PM/DataModel/User.Header.OneTimePasswords.js @@ -1,125 +1,117 @@ /* -Copyright 2008-2011 Clipperz Srl +Copyright 2008-2013 Clipperz Srl -This file is part of Clipperz Community Edition. -Clipperz Community Edition is an online password manager. +This file is part of Clipperz, the online password manager. For further information about its features and functionalities please refer to http://www.clipperz.com. -* Clipperz Community Edition is free software: you can redistribute - it and/or modify it under the terms of the GNU Affero General Public - License as published by the Free Software Foundation, either version - 3 of the License, or (at your option) any later version. +* Clipperz is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. -* Clipperz Community Edition is distributed in the hope that it will - be useful, but WITHOUT ANY WARRANTY; without even the implied - warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* Clipperz is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. * You should have received a copy of the GNU Affero General Public - License along with Clipperz Community Edition. If not, see - <http://www.gnu.org/licenses/>. + License along with Clipperz. If not, see http://www.gnu.org/licenses/. */ try { if (typeof(Clipperz.PM.DataModel.User) == 'undefined') { throw ""; }} catch (e) { throw "Clipperz.PM.DataModel.User.Header.OneTimePasswords depends on Clipperz.PM.DataModel.User!"; } if (typeof(Clipperz.PM.DataModel.User.Header) == 'undefined') { Clipperz.PM.DataModel.User.Header = {}; } //----------------------------------------------------------------------------- Clipperz.PM.DataModel.User.Header.OneTimePasswords = function(args) { Clipperz.PM.DataModel.User.Header.OneTimePasswords.superclass.constructor.apply(this, arguments); this._oneTimePasswords = null; return this; } //----------------------------------------------------------------------------- Clipperz.Base.extend(Clipperz.PM.DataModel.User.Header.OneTimePasswords, Clipperz.PM.DataModel.EncryptedRemoteObject, { 'toString': function() { return "Clipperz.PM.DataModel.User.Header.OneTimePasswords"; }, //------------------------------------------------------------------------- /* 'packData': function (someData) { // ++ var result; -console.log(">>> OneTimePasswords.packData", someData); result = Clipperz.PM.DataModel.User.Header.OneTimePasswords.superclass.packData.apply(this, arguments); -console.log("<<< OneTimePasswords.packData"); return result; }, */ //------------------------------------------------------------------------- /* 'packRemoteData': function (someData) { var result; -console.log(">>> OneTimePasswords.packRemoteData", someData); result = Clipperz.PM.DataModel.User.Header.OneTimePasswords.superclass.packRemoteData.apply(this, arguments); -console.log("<<< OneTimePasswords.packRemoteData"); return result; }, */ //------------------------------------------------------------------------- /* 'prepareRemoteDataWithKey': function (aKey) { var result; -console.log(">>> OneTimePasswords.prepareRemoteDataWithKey"); result = Clipperz.PM.DataModel.User.Header.OneTimePasswords.superclass.prepareRemoteDataWithKey.apply(this, arguments); -console.log("<<< OneTimePasswords.prepareRemoteDataWithKey"); return result; }, */ //========================================================================= 'oneTimePasswords': function () { var deferredResult; deferredResult = new Clipperz.Async.Deferred("User.Header.OneTimePasswords.oneTimePasswords", {trace:false}); if (this._oneTimePasswords == null) { deferredResult.addMethod(this, 'values') deferredResult.addCallback(MochiKit.Base.bind(function (someData) { var otpKey; this._oneTimePasswords = {}; for (otpKey in someData) { var otp; var otpParameters; otpParameters = Clipperz.Base.deepClone(someData[otpKey]); otpParameters['reference'] = otpKey; otp = new Clipperz.PM.DataModel.OneTimePassword(otpParameters); this._oneTimePasswords[otpKey] = otp; } return this._oneTimePasswords; }, this)); deferredResult.callback(); } else { deferredResult = MochiKit.Async.succeed(this._oneTimePasswords); } return deferredResult; }, //========================================================================= __syntaxFix__: "syntax fix" }); //----------------------------------------------------------------------------- diff --git a/frontend/gamma/js/Clipperz/PM/DataModel/User.Header.Preferences.js b/frontend/gamma/js/Clipperz/PM/DataModel/User.Header.Preferences.js index b164889..f1f95e8 100644 --- a/frontend/gamma/js/Clipperz/PM/DataModel/User.Header.Preferences.js +++ b/frontend/gamma/js/Clipperz/PM/DataModel/User.Header.Preferences.js @@ -1,50 +1,48 @@ /* -Copyright 2008-2011 Clipperz Srl +Copyright 2008-2013 Clipperz Srl -This file is part of Clipperz Community Edition. -Clipperz Community Edition is an online password manager. +This file is part of Clipperz, the online password manager. For further information about its features and functionalities please refer to http://www.clipperz.com. -* Clipperz Community Edition is free software: you can redistribute - it and/or modify it under the terms of the GNU Affero General Public - License as published by the Free Software Foundation, either version - 3 of the License, or (at your option) any later version. +* Clipperz is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. -* Clipperz Community Edition is distributed in the hope that it will - be useful, but WITHOUT ANY WARRANTY; without even the implied - warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* Clipperz is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. * You should have received a copy of the GNU Affero General Public - License along with Clipperz Community Edition. If not, see - <http://www.gnu.org/licenses/>. + License along with Clipperz. If not, see http://www.gnu.org/licenses/. */ try { if (typeof(Clipperz.PM.DataModel.User) == 'undefined') { throw ""; }} catch (e) { throw "Clipperz.PM.DataModel.User.Header.Preferences depends on Clipperz.PM.DataModel.User!"; } if (typeof(Clipperz.PM.DataModel.User.Header) == 'undefined') { Clipperz.PM.DataModel.User.Header = {}; } Clipperz.PM.DataModel.User.Header.Preferences = function(args) { Clipperz.PM.DataModel.User.Header.Preferences.superclass.constructor.apply(this, arguments); return this; } Clipperz.Base.extend(Clipperz.PM.DataModel.User.Header.Preferences, Clipperz.PM.DataModel.EncryptedRemoteObject, { 'toString': function() { return "Clipperz.PM.DataModel.User.Header.Preferences"; }, //------------------------------------------------------------------------- //========================================================================= __syntaxFix__: "syntax fix" }); diff --git a/frontend/gamma/js/Clipperz/PM/DataModel/User.Header.RecordIndex.js b/frontend/gamma/js/Clipperz/PM/DataModel/User.Header.RecordIndex.js index f77ea80..5681f70 100644 --- a/frontend/gamma/js/Clipperz/PM/DataModel/User.Header.RecordIndex.js +++ b/frontend/gamma/js/Clipperz/PM/DataModel/User.Header.RecordIndex.js @@ -1,702 +1,685 @@ /* -Copyright 2008-2011 Clipperz Srl +Copyright 2008-2013 Clipperz Srl -This file is part of Clipperz Community Edition. -Clipperz Community Edition is an online password manager. +This file is part of Clipperz, the online password manager. For further information about its features and functionalities please refer to http://www.clipperz.com. -* Clipperz Community Edition is free software: you can redistribute - it and/or modify it under the terms of the GNU Affero General Public - License as published by the Free Software Foundation, either version - 3 of the License, or (at your option) any later version. +* Clipperz is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. -* Clipperz Community Edition is distributed in the hope that it will - be useful, but WITHOUT ANY WARRANTY; without even the implied - warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* Clipperz is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. * You should have received a copy of the GNU Affero General Public - License along with Clipperz Community Edition. If not, see - <http://www.gnu.org/licenses/>. + License along with Clipperz. If not, see http://www.gnu.org/licenses/. */ try { if (typeof(Clipperz.PM.DataModel.User) == 'undefined') { throw ""; }} catch (e) { throw "Clipperz.PM.DataModel.User.Header.RecordIndex depends on Clipperz.PM.DataModel.User!"; } if (typeof(Clipperz.PM.DataModel.User.Header) == 'undefined') { Clipperz.PM.DataModel.User.Header = {}; } Clipperz.PM.DataModel.User.Header.RecordIndex = function(args) { Clipperz.PM.DataModel.User.Header.RecordIndex.superclass.constructor.apply(this, arguments); -//console.log("NEW Clipperz.PM.DataModel.User.Header.RecordIndex", args); this._recordsData = new Clipperz.PM.DataModel.EncryptedRemoteObject({ 'name': 'recordsData', 'retrieveKeyFunction': args.retrieveKeyFunction, 'remoteData': { 'data': args.recordsData['data'], 'version': args.encryptedDataVersion, 'recordsStats': args.recordsStats }//, // 'encryptedDataKeypath': 'data', // 'encryptedVersionKeypath': 'version' }); this._directLoginsData = new Clipperz.PM.DataModel.EncryptedRemoteObject({ 'name': 'directLoginsData', 'retrieveKeyFunction': args.retrieveKeyFunction, 'remoteData': { 'data': args.directLoginsData['data'], 'version': args.encryptedDataVersion }//, // 'encryptedDataKeypath': 'data', // 'encryptedVersionKeypath': 'version' }); this._lock = new MochiKit.Async.DeferredLock(); this._transientState = null; this._retrieveRecordDetailFunction = args.retrieveRecordDetailFunction || Clipperz.Base.exception.raise('MandatoryParameter'); this._recordsIndex = args.recordsData['index'] || Clipperz.Base.exception.raise('MandatoryParameter'); this._directLoginsIndex = args.directLoginsData['index'] || Clipperz.Base.exception.raise('MandatoryParameter'); this._records = null; return this; } Clipperz.Base.extend(Clipperz.PM.DataModel.User.Header.RecordIndex, Object, { 'toString': function() { return "Clipperz.PM.DataModel.User.Header.RecordIndex"; }, //------------------------------------------------------------------------- 'retrieveRecordDetailFunction': function () { return this._retrieveRecordDetailFunction; }, //------------------------------------------------------------------------- 'recordsIndex': function () { return this._recordsIndex; }, 'recordsData': function () { return this._recordsData; }, //------------------------------------------------------------------------- 'directLoginsIndex': function () { return this._directLoginsIndex; }, 'directLoginsData': function () { return this._directLoginsData; }, //------------------------------------------------------------------------- 'lock': function () { return this._lock; }, //------------------------------------------------------------------------- 'transientState': function () { if (this._transientState == null) { this._transientState = new Clipperz.KeyValueObjectStore(/*{'name':'User.Header.RecordIndex.transientState [1]'}*/); } return this._transientState; }, 'resetTransientState': function (isCommitting) { -//console.log("######## UserHeaderRecordIndex - resetTransientState", Clipperz.Base.deepClone(this._transientState)); if (this._transientState != null) { this._transientState.removeAllData(); } this._transientState = null; }, //------------------------------------------------------------------------- 'getRecordKey': function (aRecordReference) { return Clipperz.Async.callbacks("User.Header.RecordIndex.getRecordKey", [ MochiKit.Base.method(this, 'getRecordIndexData', aRecordReference), MochiKit.Base.itemgetter('key') ], {trace:false}); }, 'setRecordKey': function (aRecordReference, aValue) { return this.updateRecordIndexData(aRecordReference, 'key', aValue); }, //------------------------------------------------------------------------- 'getRecordIndexData': function (aRecordReference) { return this.recordsData().getValue(this.recordsIndex()[aRecordReference]); }, //......................................................................... 'updateRecordIndexData': function (aRecordReference, aKey, aValue) { return this.recordsData().setValue(this.recordsIndex()[aRecordReference]+'.'+aKey, aValue); }, //------------------------------------------------------------------------- 'getDirectLoginIndexData': function (aDirectLoginReference) { return this.directLoginsData().getValue(this.directLoginsIndex()[aDirectLoginReference]); }, 'setDirectLoginIndexData': function (aDirectLoginReference, aKey, aValue) { -//console.log("UserHeaderRecordIndex.setDirectLoginIndexData", aDirectLoginReference, this.directLoginsIndex()[aDirectLoginReference], aKey); //if (MochiKit.Base.isUndefinedOrNull(this.directLoginsIndex()[aDirectLoginReference])) { // throw "PIPPO"; //} return this.directLoginsData().setValue(this.directLoginsIndex()[aDirectLoginReference] + '.' + aKey, aValue); }, 'addDirectLoginIndexData': function (aDirectLoginReference) { -//console.log("UserHeaderRecordIndex.addDirectLoginIndexData", aDirectLoginReference, this.directLoginsIndex()[aDirectLoginReference]); return this.directLoginsData().setValue(this.directLoginsIndex()[aDirectLoginReference], {}); }, 'removeDirectLoginIndexData': function (aDirectLoginReference) { return this.directLoginsData().removeValue(this.directLoginsIndex()[aDirectLoginReference]) }, //------------------------------------------------------------------------- 'records': function () { var deferredResult; deferredResult = new Clipperz.Async.Deferred("User.Header.RecordIndex.records", {trace:false}); deferredResult.acquireLock(this.lock()); deferredResult.addCallback(MochiKit.Base.bind(function () { var innerDeferredResult; if (this._records == null) { innerDeferredResult = new Clipperz.Async.Deferred("User.Header.RecordIndex.records <inner deferred>", {trace:false}); innerDeferredResult.collectResults({ 'records': [ // MochiKit.Base.method(this.recordsData(), 'getObjectDataStore'), // MochiKit.Base.methodcaller('values') MochiKit.Base.method(this.recordsData(), 'values') ], 'recordsStats': [ MochiKit.Base.method(this.recordsData(), 'getRemoteData'), MochiKit.Base.itemgetter('recordsStats') ], 'directLogins': [ // MochiKit.Base.method(this.directLoginsData(), 'getObjectDataStore'), // MochiKit.Base.methodcaller('values') MochiKit.Base.method(this.directLoginsData(), 'values') ] }) innerDeferredResult.addCallback(MochiKit.Base.bind(function (someData) { var indexReference; var recordsInvertedIndex; var directLoginsInvertedIndex; recordsInvertedIndex = Clipperz.PM.DataModel.User.Header.RecordIndex.invertIndex(this.recordsIndex()); directLoginsInvertedIndex = Clipperz.PM.DataModel.User.Header.RecordIndex.invertIndex(this.directLoginsIndex()); this._records = {}; for (indexReference in someData['records']) { var record; var reference; var updateDate; reference = recordsInvertedIndex[indexReference]; if (typeof(someData['recordsStats'][reference]) != 'undefined') { updateDate = someData['recordsStats'][reference]['updateDate']; record = new Clipperz.PM.DataModel.Record({ 'reference': reference, 'retrieveKeyFunction': MochiKit.Base.method(this, 'getRecordKey'), 'retrieveRemoteDataFunction': this.retrieveRecordDetailFunction(), 'retrieveIndexDataFunction': MochiKit.Base.method(this, 'getRecordIndexData'), 'updateIndexDataFunction': MochiKit.Base.method(this, 'updateRecordIndexData'), 'updateDate': updateDate, 'retrieveDirectLoginIndexDataFunction': MochiKit.Base.method(this, 'getDirectLoginIndexData'), 'setDirectLoginIndexDataFunction': MochiKit.Base.method(this, 'setDirectLoginIndexData'), 'removeDirectLoginIndexDataFunction': MochiKit.Base.method(this, 'removeDirectLoginIndexData'), 'createNewDirectLoginFunction': MochiKit.Base.method(this, 'createNewDirectLogin') }); this._records[reference] = record; } else { Clipperz.log("SKIPPING record " + reference + " as there are no stas associated - " + Clipperz.Base.serializeJSON(someData['records'][reference])); // # skip the record, as it seems it is not present in the DB // updateDate = Clipperz.PM.Date.formatDateWithUTCFormat(new Date()); } } for (indexReference in someData['directLogins']) { // var directLogin; var reference; var record; reference = directLoginsInvertedIndex[indexReference]; record = this._records[recordsInvertedIndex[someData['directLogins'][indexReference]['record']]]; if (record != null) { // directLogin = new Clipperz.PM.DataModel.DirectLogin({ new Clipperz.PM.DataModel.DirectLogin({ 'reference': reference, 'record': record }); } else { -Clipperz.log("WARNING: DIRECT LOGIN without a matching RECORD!!"); -//console.log("direct login data", someData['directLogins']); -//console.log("current direct login data", someData['directLogins'][indexReference]) -//console.log("reference", reference); -//console.log("record index", this.recordsIndex()); -//console.log("record inverted index", recordsInvertedIndex); + Clipperz.logWarning("WARNING: DIRECT LOGIN without a matching RECORD!!"); } } return this._records; }, this)); innerDeferredResult.callback(); } else { innerDeferredResult = MochiKit.Async.succeed(this._records); } return innerDeferredResult; }, this)); deferredResult.releaseLock(this.lock()); deferredResult.callback(); return deferredResult; }, //------------------------------------------------------------------------- 'updateRecordIndexForNewRecord': function (aNewRecord) { var newRecordIndex; var recordReference; recordReference = aNewRecord.reference(); newRecordIndex = (MochiKit.Base.listMax(MochiKit.Base.map(MochiKit.Base.partial(MochiKit.Base.operator.mul, 1), MochiKit.Base.values(this.recordsIndex()))) + 1) + ''; this.recordsIndex()[recordReference] = newRecordIndex; this.transientState().setValue('newlyCreatedRecordsIndex' + '.' + recordReference, newRecordIndex); this.transientState().setValue('newlyCreatedRecordsReferences' + '.' + recordReference, aNewRecord); }, //......................................................................... 'createNewRecord': function () { var deferredResult; var newRecord; -//console.log("#### new Clipperz.PM.DataModel.Record [4]"); newRecord = new Clipperz.PM.DataModel.Record({ 'retrieveKeyFunction': MochiKit.Base.method(this, 'getRecordKey'), 'retrieveRemoteDataFunction': this.retrieveRecordDetailFunction(), 'retrieveIndexDataFunction': MochiKit.Base.method(this, 'getRecordIndexData'), 'updateIndexDataFunction': MochiKit.Base.method(this, 'updateRecordIndexData'), 'updateDate': Clipperz.PM.Date.formatDateWithUTCFormat(new Date()), 'retrieveDirectLoginIndexDataFunction': MochiKit.Base.method(this, 'getDirectLoginIndexData'), 'setDirectLoginIndexDataFunction': MochiKit.Base.method(this, 'setDirectLoginIndexData'), 'removeDirectLoginIndexDataFunction': MochiKit.Base.method(this, 'removeDirectLoginIndexData'), 'createNewDirectLoginFunction': MochiKit.Base.method(this, 'createNewDirectLogin') }); this.transientState().setValue('newRecordsReferences' + '.' + newRecord.reference(), newRecord); this.updateRecordIndexForNewRecord(newRecord); deferredResult = Clipperz.Async.callbacks("User.Header.RecordIndex.createNewRecord", [ MochiKit.Base.method(this, 'records'), MochiKit.Base.partial(Clipperz.Async.setItemOnObject, newRecord.reference(), newRecord), MochiKit.Base.method(this, 'setRecordKey', newRecord.reference(), Clipperz.PM.Crypto.randomKey()), MochiKit.Base.method(newRecord, 'setLabel', ''), MochiKit.Base.partial(MochiKit.Async.succeed, newRecord) ], {trace:false}); return deferredResult; }, //------------------------------------------------------------------------- 'deleteRecord': function (aRecord) { var deferredResult; var recordReference; recordReference = aRecord.reference(); deferredResult = new Clipperz.Async.Deferred("User.Header.RecordIndex.deleteRecord", {trace:false}); deferredResult.addMethod(aRecord, 'directLogins'); deferredResult.addCallback(MochiKit.Base.values); deferredResult.addCallback(MochiKit.Base.map, MochiKit.Base.method(this, 'removeDirectLogin')); deferredResult.addMethod(this.recordsData(), 'removeValue', this.recordsIndex()[recordReference]); deferredResult.addCallback(MochiKit.Base.bind(function () { this.transientState().setValue('deleteRecordsIndex' + '.' + recordReference, this.recordsIndex()[recordReference]); delete this.recordsIndex()[recordReference]; }, this)); deferredResult.addMethod(this, 'records'); deferredResult.addCallback(MochiKit.Base.itemgetter(recordReference)); deferredResult.addMethod(this.transientState(), 'setValue', 'deleteRecordsReferences' + '.' + recordReference); deferredResult.addMethod(this, 'records'); deferredResult.addCallback(MochiKit.Base.bind(function (someRecords) { delete someRecords[recordReference]; }, this)); deferredResult.callback(); return deferredResult; }, //========================================================================= 'removeDirectLogin': function (aDirectLogin) { this.directLoginsData().removeValue(this.directLoginsIndex()[aDirectLogin.reference()]); }, //------------------------------------------------------------------------- 'createNewDirectLogin': function (aRecord) { var newDirectLogin; var newDirectLoginIndexValue; newDirectLogin = new Clipperz.PM.DataModel.DirectLogin({record:aRecord}); newDirectLoginIndexValue = MochiKit.Base.listMax(MochiKit.Base.map(function (aValue) { return aValue * 1; }, MochiKit.Base.values(this.directLoginsIndex()))) + 1; this.transientState().setValue('newDirectLoginReferences' + '.' + newDirectLogin.reference(), newDirectLogin); -//console.log("UserHeaderRecordIndex.createNewDirectLogin [1]", newDirectLogin.reference(), newDirectLoginIndexValue); this.directLoginsIndex()[newDirectLogin.reference()] = newDirectLoginIndexValue; -//console.log("UserHeaderRecordIndex.createNewDirectLogin [2]", newDirectLogin.reference(), this.directLoginsIndex()[newDirectLogin.reference()]); this.directLoginsData().setValue(this.directLoginsIndex()[newDirectLogin.reference()], {'record': this.recordsIndex()[aRecord.reference()]}); return newDirectLogin; }, //========================================================================= 'deleteAllCleanTextData': function () { return Clipperz.Async.callbacks("User.Header.RecordIndex.deleteAllCleanTextData", [ // MochiKit.Base.method(this, 'records'), // MochiKit.Base.values, // MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('deleteAllCleanTextData')), MochiKit.Base.method(this, 'recordsData'), MochiKit.Base.methodcaller('deleteAllCleanTextData'), MochiKit.Base.method(this, 'directLoginsData'), MochiKit.Base.methodcaller('deleteAllCleanTextData') ], {trace:false}); }, //------------------------------------------------------------------------- 'hasAnyCleanTextData': function () { var deferredResult; deferredResult = new Clipperz.Async.Deferred({trace:false}); deferredResult.collectResults({ 'recordsData': [ MochiKit.Base.method(this, 'recordsData'), MochiKit.Base.methodcaller('hasAnyCleanTextData') ], 'directLoginsData': [ MochiKit.Base.method(this, 'directLoginsData'), MochiKit.Base.methodcaller('hasAnyCleanTextData') ], // 'records': [ // MochiKit.Base.method(this, 'records'), // MochiKit.Base.values, // MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('hasAnyCleanTextData')), // Clipperz.Async.collectAll // ] }); -//deferredResult.addCallback(function (aValue) { console.log("USER.Header.RecordIndex.hasAnyCleanTextData", aValue); return aValue}); // deferredResult.addCallback(MochiKit.Base.values); // deferredResult.addCallback(MochiKit.Base.flattenArguments); // deferredResult.addCallback(function(someValues) { // return MochiKit.Iter.some(someValues, MochiKit.Base.operator.identity); // }); deferredResult.addCallback(Clipperz.Async.or); deferredResult.callback(); return deferredResult; }, //------------------------------------------------------------------------- 'hasPendingChanges': function () { var deferredResult; deferredResult = new Clipperz.Async.Deferred("User.Header.RecordIndex.hasPendingChanges", {trace:false}); deferredResult.collectResults({ 'recordsData': [ MochiKit.Base.method(this, 'recordsData'), MochiKit.Base.methodcaller('hasPendingChanges') ], 'directLoginsData': [ MochiKit.Base.method(this, 'directLoginsData'), MochiKit.Base.methodcaller('hasPendingChanges') ] }); -//deferredResult.addCallback(function (aValue) { console.log("UserHeaderIndex.hasPendingResults", aValue); return aValue; }); deferredResult.addCallback(Clipperz.Async.or); // deferredResult.addCallback(MochiKit.Base.values); // deferredResult.addCallback(MochiKit.Base.flattenArguments); // deferredResult.addCallback(function(someValues) { // return MochiKit.Iter.some(someValues, MochiKit.Base.operator.identity); // }); deferredResult.callback(); return deferredResult; }, //------------------------------------------------------------------------- 'commitTransientState': function () { var deferredResult; deferredResut = Clipperz.Async.callbacks("User.Header.RecordIndex.commitTransientState", [ MochiKit.Base.method(this, 'recordsData'), MochiKit.Base.methodcaller('commitTransientState'), MochiKit.Base.method(this, 'directLoginsData'), MochiKit.Base.methodcaller('commitTransientState'), MochiKit.Base.method(this, 'resetTransientState', true) ], {trace:false}); return deferredResult; }, //------------------------------------------------------------------------- 'revertChanges': function () { return Clipperz.Async.callbacks("User.Header.RecordIndex.revertChanges", [ MochiKit.Base.method(this, 'recordsData'), MochiKit.Base.methodcaller('revertChanges'), // MochiKit.Base.method(this, 'directLoginsData'), // MochiKit.Base.methodcaller('revertChanges'), MochiKit.Base.method(this, 'records'), MochiKit.Base.bind(function (someRecords) { var recordReference; for (recordReference in this.transientState().getValue('deleteRecordsReferences')) { this.recordsIndex()[recordReference] = this.transientState().getValue('deleteRecordsIndex' + '.' + recordReference); someRecords[recordReference] = this.transientState().getValue('deleteRecordsReferences' + '.' + recordReference); } for (recordReference in this.transientState().getValue('newRecordsReferences')) { delete this.recordsIndex()[recordReference]; delete someRecords[recordReference]; } }, this), // MochiKit.Base.method(this, 'directLogins'), MochiKit.Base.bind(function () { var directLoginReference; // this.transientState().setValue('newDirectLoginReferences' + '.' + newDirectLogin.reference(), newDirectLogin); // // this.directLoginsIndex()[newDirectLogin.reference()] = newDirectLoginIndexValue; // this.directLoginsData().setValue(this.directLoginsIndex()[newDirectLogin.reference()], {'record': this.recordsIndex()[aRecord.reference()]}); // for (directLoginReference in this.transientState().getValue('deleteDirectLoginReferences')) { // someDirectLogins[directLoginReference] = this.transientState().getValue('deleteDirectLoginReferences' + '.' + recordReference); // } for (directLoginReference in this.transientState().getValue('newDirectLoginReferences')) { // this.directLoginsData().removeValue(this.directLoginsIndex()[directLoginReference]); delete this.directLoginsIndex()[directLoginReference]; } }, this), MochiKit.Base.method(this, 'directLoginsData'), MochiKit.Base.methodcaller('revertChanges'), MochiKit.Base.method(this, 'resetTransientState', false) ], {trace:false}); }, //------------------------------------------------------------------------- 'prepareRemoteDataWithKey': function (aKey) { // "records": { // "index": { // "eeda70e0392261967bda71c3764da78989c45bbd2bb7be6b941b90f81d9b81b5": "0", // "13a5e52976337ab210903cd04872588e1b21fb72bc183e91aa25c494b8138551": "1", // ... // "465a067a0bd2b470fa834de5397e38494de0c7707938262fae3427932e219744": "18", // "4fd1dc2ca860b7fb47cef10a84edb3270da05510b0a30a6b0b083898712d4b9e": "19" // }, // "data": "n+AzGEEQXaSRSY4d ... BDypotrXgPo94uHfoXvGFzwCn8w=" // }, // "directLogins": { // "index": { // "61e87fdc4f1d9112e3b30c1f6812d095dcdb24f014c83319091eb6c9899ec348":"0", // "989593d4c48929f0c8f1581aa96969c622807e99619ed4732026e967530a68ad":"1", // ... // "cb9ae0bba1957075ccdbfd3b3481704d62087687a2ac7c411a4f07d444bde0f7":"17", // "7e1d069b7fa57c03bd7bf48807520feb953157834503aaff8c9d493f37dea69d":"18" // }, // "data":"5YG9KKU/OZ5guUgFlms6k1 ... ZG/5Fn0uN+LoAsNfHm+EE62x" // }, var deferredResult; var result; -//console.log("recordsIndex", this.recordsIndex()); result = {}; deferredResult = new Clipperz.Async.Deferred("User.Header.RecordIndex.prepareRemoteDataWithKey", {trace:false}); deferredResult.collectResults({ 'index': MochiKit.Base.partial(MochiKit.Async.succeed, this.recordsIndex()), 'data': [ MochiKit.Base.method(this.recordsData(), 'prepareRemoteDataWithKey', aKey), MochiKit.Base.itemgetter('data') ] }); deferredResult.addCallback(Clipperz.Async.setItem, result, 'records'); deferredResult.collectResults({ 'index': MochiKit.Base.partial(MochiKit.Async.succeed, this.directLoginsIndex()), 'data': [ MochiKit.Base.method(this.directLoginsData(), 'prepareRemoteDataWithKey', aKey), MochiKit.Base.itemgetter('data') ] }); deferredResult.addCallback(Clipperz.Async.setItem, result, 'directLogins'); deferredResult.addCallback(MochiKit.Async.succeed, result); deferredResult.callback(); return deferredResult; }, //------------------------------------------------------------------------- 'updateRecordKeyAndPrepareRemoteData': function (aRecord) { var newRecordKey; var deferredResult; newRecordKey = Clipperz.PM.Crypto.randomKey(); deferredResult = new Clipperz.Async.Deferred("User.Header.RecordIndex.updateRecordKeyAndPrepareRemoteData", {trace:false}); deferredResult.addCallback(MochiKit.Base.method(aRecord, 'prepareRemoteDataWithKey', newRecordKey)); deferredResult.addCallbackPass(MochiKit.Base.method(this, 'setRecordKey', aRecord.reference(), newRecordKey)); deferredResult.callback(); return deferredResult; }, //......................................................................... 'removeNewRecordWithNoChanges': function (aRecord) { var deferredResult; var recordReference; recordReference = aRecord.reference(); deferredResult = new Clipperz.Async.Deferred("User.Header.RecordIndex.removeNewRecordWithNoChanges", {trace:false}); deferredResult.addMethod(this.recordsData(), 'removeValue', this.recordsIndex()[recordReference]); deferredResult.addCallback(MochiKit.Base.bind(function () { delete this.recordsIndex()[recordReference]; }, this)); deferredResult.addMethod(this, 'records'); deferredResult.addCallback(MochiKit.Base.bind(function (someRecords) { delete someRecords[recordReference]; }, this)); deferredResult.callback(); return deferredResult; }, //......................................................................... 'prepareRemoteDataForChangedRecords': function () { var deferredResult; var result; result = {}; deferredResult = new Clipperz.Async.Deferred("User.Header.RecordIndex.prepareRemoteDataForChangedRecords", {trace:false}); deferredResult.addMethod(this, 'records'); deferredResult.addCallback(MochiKit.Base.values); deferredResult.addCallback(Clipperz.Async.deferredFilter, MochiKit.Base.methodcaller('isBrandNewWithNoPendingChanges')); deferredResult.addCallback(MochiKit.Base.map, MochiKit.Base.method(this, 'removeNewRecordWithNoChanges')); deferredResult.addMethod(this, 'records'); deferredResult.addCallback(MochiKit.Base.values); deferredResult.addCallback(Clipperz.Async.deferredFilter, MochiKit.Base.methodcaller('hasPendingChanges')); deferredResult.addCallback(MochiKit.Base.map, MochiKit.Base.method(this, 'updateRecordKeyAndPrepareRemoteData')); deferredResult.addCallback(Clipperz.Async.collectAll); deferredResult.addCallback(Clipperz.Async.deferredIf("updated records != null", [ MochiKit.Base.operator.identity ], [ MochiKit.Base.partial(MochiKit.Async.succeed, []) ])); deferredResult.addCallback(Clipperz.Async.setItem, result, 'updated'); deferredResult.addMethod(this.transientState(), 'getValue', 'deleteRecordsReferences'); deferredResult.addCallback(MochiKit.Base.keys); deferredResult.addCallback(Clipperz.Async.deferredIf("deleted records != null", [ MochiKit.Base.operator.identity ], [ MochiKit.Base.partial(MochiKit.Async.succeed, []) ])); deferredResult.addCallback(Clipperz.Async.setItem, result, 'deleted'); deferredResult.addCallback(MochiKit.Async.succeed, result); deferredResult.callback(); return deferredResult; }, //------------------------------------------------------------------------- __syntaxFix__: "syntax fix" }); Clipperz.PM.DataModel.User.Header.RecordIndex.invertIndex = function (anIndex) { var result; var key; result = {}; for (key in anIndex) { result[anIndex[key]] = key; } return result; };
\ No newline at end of file diff --git a/frontend/gamma/js/Clipperz/PM/DataModel/User.js b/frontend/gamma/js/Clipperz/PM/DataModel/User.js index 646ce21..fd18faf 100644 --- a/frontend/gamma/js/Clipperz/PM/DataModel/User.js +++ b/frontend/gamma/js/Clipperz/PM/DataModel/User.js @@ -1,804 +1,800 @@ /* -Copyright 2008-2011 Clipperz Srl +Copyright 2008-2013 Clipperz Srl -This file is part of Clipperz Community Edition. -Clipperz Community Edition is an online password manager. +This file is part of Clipperz, the online password manager. For further information about its features and functionalities please refer to http://www.clipperz.com. -* Clipperz Community Edition is free software: you can redistribute - it and/or modify it under the terms of the GNU Affero General Public - License as published by the Free Software Foundation, either version - 3 of the License, or (at your option) any later version. +* Clipperz is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. -* Clipperz Community Edition is distributed in the hope that it will - be useful, but WITHOUT ANY WARRANTY; without even the implied - warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* Clipperz is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. * You should have received a copy of the GNU Affero General Public - License along with Clipperz Community Edition. If not, see - <http://www.gnu.org/licenses/>. + License along with Clipperz. If not, see http://www.gnu.org/licenses/. */ if (typeof(Clipperz) == 'undefined') { Clipperz = {}; } if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; } if (typeof(Clipperz.PM.DataModel) == 'undefined') { Clipperz.PM.DataModel = {}; } //############################################################################# Clipperz.PM.DataModel.User = function (args) { args = args || {}; Clipperz.PM.DataModel.User.superclass.constructor.apply(this, arguments); this._username = args.username || null; this._getPassphraseFunction = args.getPassphraseFunction || null; this._data = null; this._connection = null; this._connectionVersion = 'current'; this._serverData = null; // this._serverLockValue = null; this._transientState = null; this._deferredLocks = { 'passphrase': new MochiKit.Async.DeferredLock(), 'serverData': new MochiKit.Async.DeferredLock(), // 'recordsIndex': new MochiKit.Async.DeferredLock(), // 'directLoginsIndex': new MochiKit.Async.DeferredLock() // 'preferences': new MochiKit.Async.DeferredLock() // 'oneTimePasswords': new MochiKit.Async.DeferredLock() '__syntaxFix__': 'syntax fix' }; return this; } Clipperz.Base.extend(Clipperz.PM.DataModel.User, Object, { 'toString': function () { return "Clipperz.PM.DataModel.User - " + this.username(); }, //------------------------------------------------------------------------- 'username': function () { return this._username; }, 'setUsername': function (aValue) { this._username = aValue; }, //------------------------------------------------------------------------- 'displayName': function() { return "" + this.username() + ""; }, //------------------------------------------------------------------------- 'data': function () { if (this._data == null) { this._data = new Clipperz.KeyValueObjectStore(/*{'name':'User.data [1]'}*/); }; return this._data; }, //------------------------------------------------------------------------- /* 'serverLockValue': function () { return this._serverLockValue; }, 'setServerLockValue': function (aValue) { this._serverLockValue = aValue; }, */ //------------------------------------------------------------------------- 'transientState': function () { if (this._transientState == null) { this._transientState = {} } return this._transientState; }, 'resetTransientState': function (isCommitting) { this._transientState = null; }, //------------------------------------------------------------------------- 'deferredLockForSection': function(aSectionName) { return this._deferredLocks[aSectionName]; }, //------------------------------------------------------------------------- 'getPassphrase': function() { var deferredResult; deferredResult = new Clipperz.Async.Deferred("User.getPassphrase", {trace:false}); deferredResult.acquireLock(this.deferredLockForSection('passphrase')); deferredResult.addMethod(this.data(), 'deferredGetOrSet', 'passphrase', this.getPassphraseFunction()); deferredResult.releaseLock(this.deferredLockForSection('passphrase')); deferredResult.callback(); return deferredResult; }, 'getPassphraseFunction': function () { return this._getPassphraseFunction; }, //------------------------------------------------------------------------- 'getCredentials': function () { return Clipperz.Async.collectResults("User; get username and passphrase", { 'username': MochiKit.Base.method(this, 'username'), 'password': MochiKit.Base.method(this, 'getPassphrase') }, {trace:false})(); }, //------------------------------------------------------------------------- 'changePassphrase': function (aNewValue) { return this.updateCredentials(this.username(), aNewValue); }, //......................................................................... 'updateCredentials': function (aUsername, aPassphrase) { var deferredResult; deferredResult = new Clipperz.Async.Deferred("User.updateCredentials", {trace:false}); // deferredResult.addMethod(this, 'getPassphrase'); // deferredResult.setValue('currentPassphrase'); deferredResult.addMethod(this.connection(), 'ping'); deferredResult.addMethod(this, 'setUsername', aUsername) deferredResult.acquireLock(this.deferredLockForSection('passphrase')); deferredResult.addMethod(this.data(), 'deferredGetOrSet', 'passphrase', aPassphrase); deferredResult.releaseLock(this.deferredLockForSection('passphrase')); // deferredResult.getValue('currentPassphrase'); deferredResult.addMethod(this, 'prepareRemoteDataWithKey', aPassphrase); deferredResult.addMethod(this.connection(), 'updateCredentials', aUsername, aPassphrase); deferredResult.callback(); return deferredResult; }, //------------------------------------------------------------------------- 'initialSetupWithNoData': function () { this._serverData = { 'version': '0.1', 'statistics': "", 'header': { 'data': null, 'version': Clipperz.PM.Crypto.encryptingFunctions.currentVersion, 'recordsIndex': new Clipperz.PM.DataModel.User.Header.RecordIndex({ 'retrieveKeyFunction': MochiKit.Base.method(this, 'getPassphrase'), 'recordsData': {'data':null, 'index':{}}, 'recordsStats': null, 'directLoginsData': {'data':null, 'index':{}}, 'encryptedDataVersion': Clipperz.PM.Crypto.encryptingFunctions.currentVersion, 'retrieveRecordDetailFunction': MochiKit.Base.method(this, 'getRecordDetail') }), 'preferences': new Clipperz.PM.DataModel.User.Header.Preferences({ 'name': 'preferences', 'retrieveKeyFunction': MochiKit.Base.method(this, 'getPassphrase') }), 'oneTimePasswords': new Clipperz.PM.DataModel.User.Header.OneTimePasswords({ 'name': 'preferences', 'retrieveKeyFunction': MochiKit.Base.method(this, 'getPassphrase') }) } }; // this._serverLockValue = Clipperz.PM.Crypto.randomKey(); }, //......................................................................... 'registerAsNewAccount': function () { var deferredResult; deferredResult = new Clipperz.Async.Deferred("User.registerAsNewAccount", {trace:false}); deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'updateProgress', {'extraSteps':3}); deferredResult.addMethod(this, 'initialSetupWithNoData') deferredResult.addMethod(this, 'getPassphrase'); deferredResult.addMethod(this, 'prepareRemoteDataWithKey'); deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress'); deferredResult.addMethod(this.connection(), 'register'); // deferredResult.addCallback(MochiKit.Base.itemgetter('lock')); // deferredResult.addMethod(this, 'setServerLockValue'); deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'userSuccessfullyRegistered'); // deferredResult.addErrback (MochiKit.Base.method(this, 'handleRegistrationFailure')); deferredResult.callback(); return deferredResult; }, //------------------------------------------------------------------------- 'login': function () { var deferredResult; deferredResult = new Clipperz.Async.Deferred("User.login", {trace:false}); deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'updateProgress', {'extraSteps':3}); deferredResult.addMethod(this, 'getPassphrase'); deferredResult.addCallback(Clipperz.PM.DataModel.OneTimePassword.isValidOneTimePasswordValue); deferredResult.addCallback(Clipperz.Async.deferredIf("Is the passphrase an OTP", [ MochiKit.Base.partial(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'updateProgress', {'extraSteps':1}), MochiKit.Base.method(this, 'getCredentials'), MochiKit.Base.method(this.connection(), 'redeemOneTimePassword'), MochiKit.Base.method(this.data(), 'setValue', 'passphrase') ], [])); deferredResult.addErrback(MochiKit.Base.method(this, 'getPassphrase')); deferredResult.addMethod(this.connection(), 'login', false); deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'userSuccessfullyLoggedIn'); deferredResult.addErrback (MochiKit.Base.method(this, 'handleConnectionFallback')); deferredResult.callback(); return deferredResult; }, //......................................................................... 'handleConnectionFallback': function(aValue) { var result; if (aValue instanceof MochiKit.Async.CancelledError) { result = aValue; } else { this.setConnectionVersion(Clipperz.PM.Connection.communicationProtocol.fallbackVersions[this.connectionVersion()]); if (this.connectionVersion() != null) { result = new Clipperz.Async.Deferred("User.handleConnectionFallback - retry"); result.addMethod(this, 'login'); result.callback(); } else { result = Clipperz.Async.callbacks("User.handleConnectionFallback - failed", [ MochiKit.Base.method(this.data(), 'removeValue', 'passphrase'), MochiKit.Base.method(this, 'setConnectionVersion', 'current'), MochiKit.Base.partial(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'userLoginFailed'), MochiKit.Base.partial(MochiKit.Async.fail, Clipperz.PM.DataModel.User.exception.LoginFailed) ], {trace:false}); } } return result; }, //------------------------------------------------------------------------- 'lock': function () { return Clipperz.Async.callbacks("User.lock", [ MochiKit.Base.method(this, 'deleteAllCleanTextData') ], {trace:false}); }, //------------------------------------------------------------------------- 'logout': function () { return Clipperz.Async.callbacks("User.logout", [ MochiKit.Base.method(this, 'deleteAllCleanTextData'), MochiKit.Base.method(this.connection(), 'logout') ], {trace:false}); }, //------------------------------------------------------------------------- 'headerFormatVersion': function(anHeader) { var result; if (anHeader.charAt(0) == '{') { var headerData; headerData = Clipperz.Base.evalJSON(anHeader); result = headerData['version']; } else { result = 'LEGACY'; } return result; }, //------------------------------------------------------------------------- 'unpackServerData': function (someServerData) { var unpackedData; var headerVersion; var recordsIndex; var preferences; var oneTimePasswords; -//console.log(">>> ***************** user.unpackServerData", someServerData); // this.setServerLockValue(someServerData['lock']); headerVersion = this.headerFormatVersion(someServerData['header']); switch (headerVersion) { case 'LEGACY': var legacyHeader; legacyHeader = new Clipperz.PM.DataModel.User.Header.Legacy({ 'retrieveKeyFunction': MochiKit.Base.method(this, 'getPassphrase'), 'remoteData': { 'data': someServerData['header'], 'version': someServerData['version'], 'recordsStats': someServerData['recordsStats'] }, // 'encryptedDataKeypath': 'data', // 'encryptedVersionKeypath': 'version', 'retrieveRecordDetailFunction': MochiKit.Base.method(this, 'getRecordDetail') }); recordsIndex = legacyHeader; preferences = legacyHeader; oneTimePasswords = legacyHeader; break; case '0.1': var headerData; headerData = Clipperz.Base.evalJSON(someServerData['header']); recordsIndex = new Clipperz.PM.DataModel.User.Header.RecordIndex({ 'retrieveKeyFunction': MochiKit.Base.method(this, 'getPassphrase'), 'recordsData': headerData['records'], 'recordsStats': someServerData['recordsStats'], 'directLoginsData': headerData['directLogins'], 'encryptedDataVersion': someServerData['version'], 'retrieveRecordDetailFunction': MochiKit.Base.method(this, 'getRecordDetail') }); // Still missing a test case that actually fais with the old version of the code, where the check for undefined was missing if (typeof(headerData['preferences']) != 'undefined') { preferences = new Clipperz.PM.DataModel.User.Header.Preferences({ 'name': 'preferences', 'retrieveKeyFunction': MochiKit.Base.method(this, 'getPassphrase'), 'remoteData': { 'data': headerData['preferences']['data'], 'version': someServerData['version'] } }); } else { preferences = new Clipperz.PM.DataModel.User.Header.Preferences({ 'name': 'preferences', 'retrieveKeyFunction': MochiKit.Base.method(this, 'getPassphrase') }); } if (typeof(headerData['oneTimePasswords']) != 'undefined') { oneTimePasswords = new Clipperz.PM.DataModel.User.Header.OneTimePasswords({ 'name': 'preferences', 'retrieveKeyFunction': MochiKit.Base.method(this, 'getPassphrase'), 'remoteData': { 'data': headerData['oneTimePasswords']['data'], 'version': someServerData['version'] } }); } else { oneTimePasswords = new Clipperz.PM.DataModel.User.Header.OneTimePasswords({ 'name': 'preferences', 'retrieveKeyFunction': MochiKit.Base.method(this, 'getPassphrase') }); } break; } unpackedData = { 'version': someServerData['version'], 'statistics': someServerData['statistics'], 'header': { 'data': someServerData['header'], 'version': headerVersion, 'recordsIndex': recordsIndex, 'preferences': preferences, 'oneTimePasswords': oneTimePasswords } }; this._serverData = unpackedData; -//console.log("<<< ***************** user.unpackServerData", this._serverData); return this._serverData; }, //------------------------------------------------------------------------- 'getServerData': function() { var deferredResult; deferredResult = new Clipperz.Async.Deferred("User.getServerData", {trace:false}); deferredResult.acquireLock(this.deferredLockForSection('serverData')); deferredResult.addCallback(MochiKit.Base.bind(function(aResult) { var innerDeferredResult; innerDeferredResult = new Clipperz.Async.Deferred("User.getUserDetails.innerDeferred", {trace:false}); if (this._serverData == null) { innerDeferredResult.addCallbackPass(MochiKit.Signal.signal, this, 'loadingUserDetails'); innerDeferredResult.addMethod(this.connection(), 'message', 'getUserDetails'); innerDeferredResult.addMethod(this, 'unpackServerData'); innerDeferredResult.addCallbackPass(MochiKit.Signal.signal, this, 'loadedUserDetails'); } innerDeferredResult.addCallback(MochiKit.Base.bind(function () { return this._serverData; },this)); innerDeferredResult.callback(); return innerDeferredResult; }, this)); deferredResult.releaseLock(this.deferredLockForSection('serverData')); deferredResult.callback(); return deferredResult; }, //------------------------------------------------------------------------- 'connectionVersion': function() { return this._connectionVersion; }, 'setConnectionVersion': function(aValue) { if (this._connectionVersion != aValue) { this.resetConnection(); } this._connectionVersion = aValue; }, //------------------------------------------------------------------------- 'connection': function() { if ((this._connection == null) && (this.connectionVersion() != null) ){ this._connection = new Clipperz.PM.Connection.communicationProtocol.versions[this.connectionVersion()]({ getCredentialsFunction: MochiKit.Base.method(this, 'getCredentials') }); } return this._connection; }, 'resetConnection': function(aValue) { if (this._connection != null) { this._connection.reset(); } this._connection = null; }, //========================================================================= 'getHeaderIndex': function (aKey) { return Clipperz.Async.callbacks("User.getHeaderIndex", [ MochiKit.Base.method(this, 'getServerData'), MochiKit.Base.itemgetter('header'), MochiKit.Base.itemgetter(aKey) ], {trace:false}) }, //========================================================================= 'getRecords': function () { return Clipperz.Async.callbacks("User.getRecords", [ MochiKit.Base.method(this, 'getHeaderIndex', 'recordsIndex'), MochiKit.Base.methodcaller('records'), MochiKit.Base.values ], {trace:false}); }, 'recordWithLabel': function (aLabel) { return Clipperz.Async.callbacks("User.recordWithLabel", [ MochiKit.Base.method(this, 'getRecords'), MochiKit.Base.partial(Clipperz.Async.deferredFilter, function (aRecord) { return Clipperz.Async.callbacks("User.recordWithLabel - check record label", [ MochiKit.Base.methodcaller('label'), MochiKit.Base.partial(MochiKit.Base.operator.eq, aLabel) ], {trace:false}, aRecord); }), function (someFilteredResults) { var result; switch (someFilteredResults.length) { case 0: result = null; break; case 1: result = someFilteredResults[0]; break; default: WTF = TODO; break; } return result; } ], {trace:false}); }, //------------------------------------------------------------------------- 'getRecord': function (aRecordReference) { return Clipperz.Async.callbacks("User.getRecord", [ MochiKit.Base.method(this, 'getHeaderIndex', 'recordsIndex'), MochiKit.Base.methodcaller('records'), MochiKit.Base.itemgetter(aRecordReference), Clipperz.Async.deferredIf("record != null", [ MochiKit.Base.operator.identity ], [ function () { throw "Record does not exists"} ]) ], {trace:false}); }, //------------------------------------------------------------------------- 'getRecordDetail': function (aRecordReference) { return this.connection().message('getRecordDetail', {reference: aRecordReference}); }, //------------------------------------------------------------------------- 'deleteRecord': function (aRecord) { return Clipperz.Async.callbacks("User.deleteRecord", [ MochiKit.Base.method(this, 'getHeaderIndex', 'recordsIndex'), MochiKit.Base.methodcaller('deleteRecord', aRecord) ], {trace:false}); }, //------------------------------------------------------------------------- 'createNewRecord': function () { return Clipperz.Async.callbacks("User.createNewRecord", [ MochiKit.Base.method(this, 'getHeaderIndex', 'recordsIndex'), MochiKit.Base.methodcaller('createNewRecord') ], {trace:false}); }, //========================================================================= 'getDirectLogins': function() { var deferredResult; deferredResult = new Clipperz.Async.Deferred("User.getDirectLogins", {trace:false}); deferredResult.addMethod(this, 'getRecords'); deferredResult.addCallback(MochiKit.Base.map, MochiKit.Base.compose(MochiKit.Base.values, MochiKit.Base.methodcaller('directLogins'))); deferredResult.addCallback(MochiKit.Base.flattenArray); deferredResult.callback(); return deferredResult; }, //========================================================================= 'getOneTimePasswords': function () { return Clipperz.Async.callbacks("User.getOneTimePasswords", [ MochiKit.Base.method(this, 'getHeaderIndex', 'oneTimePasswords'), MochiKit.Base.methodcaller('oneTimePasswords'), MochiKit.Base.values ], {trace:false}); }, //========================================================================= 'invokeMethodNamedOnHeader': function (aMethodName, aValue) { return Clipperz.Async.collectResults("User.invokeMethodNamedOnHeader [" + aMethodName + "]", { 'recordIndex': [ MochiKit.Base.method(this, 'getHeaderIndex', 'recordsIndex'), MochiKit.Base.methodcaller(aMethodName, aValue) ], 'preferences': [ MochiKit.Base.method(this, 'getHeaderIndex', 'preferences'), MochiKit.Base.methodcaller(aMethodName, aValue) ], 'oneTimePasswords': [ MochiKit.Base.method(this, 'getHeaderIndex', 'oneTimePasswords'), MochiKit.Base.methodcaller(aMethodName, aValue) ]//, // 'statistics': [ // MochiKit.Base.method(this, 'getStatistics'), // MochiKit.Base.methodcaller(aMethodName, aValue) // ] }, {trace:false})(); }, //------------------------------------------------------------------------- 'invokeMethodNamedOnRecords': function (aMethodName, aValue) { return Clipperz.Async.callbacks("User.invokeMethodNamedOnRecords[" + aMethodName + "]", [ MochiKit.Base.method(this, 'getRecords'), MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller(aMethodName, aValue)), Clipperz.Async.collectAll ], {trace:false}); }, //========================================================================= 'hasPendingChanges': function () { var deferredResult; deferredResult = new Clipperz.Async.Deferred("User.hasPendingChanges", {trace:false}); deferredResult.collectResults({ 'header': [ MochiKit.Base.method(this, 'invokeMethodNamedOnHeader', 'hasPendingChanges'), MochiKit.Base.values ], 'records': MochiKit.Base.method(this, 'invokeMethodNamedOnRecords', 'hasPendingChanges') }); deferredResult.addCallback(Clipperz.Async.or); deferredResult.callback(); // recordsIndex = legacyHeader; // preferences = legacyHeader; // oneTimePasswords = legacyHeader; return deferredResult; }, //========================================================================= 'commitTransientState': function () { return Clipperz.Async.callbacks("User.commitTransientState", [ MochiKit.Base.method(this, 'invokeMethodNamedOnHeader', 'commitTransientState'), MochiKit.Base.method(this, 'invokeMethodNamedOnRecords', 'commitTransientState'), MochiKit.Base.method(this, 'transientState'), // MochiKit.Base.itemgetter('lock'), // MochiKit.Base.method(this, 'setServerLockValue'), MochiKit.Base.method(this, 'resetTransientState', true) ], {trace:false}); }, //------------------------------------------------------------------------- 'revertChanges': function () { return Clipperz.Async.callbacks("User.revertChanges", [ MochiKit.Base.method(this, 'invokeMethodNamedOnHeader', 'revertChanges'), MochiKit.Base.method(this, 'invokeMethodNamedOnRecords', 'revertChanges'), MochiKit.Base.method(this, 'resetTransientState', false) ], {trace:false}); }, //========================================================================= 'deleteAllCleanTextData': function () { return Clipperz.Async.callbacks("User.deleteAllCleanTextData", [ MochiKit.Base.method(this, 'invokeMethodNamedOnRecords', 'deleteAllCleanTextData'), MochiKit.Base.method(this, 'invokeMethodNamedOnHeader', 'deleteAllCleanTextData'), MochiKit.Base.method(this.data(), 'removeAllData'), MochiKit.Base.method(this, 'resetTransientState', false) ], {trace:false}); }, //------------------------------------------------------------------------- 'hasAnyCleanTextData': function () { var deferredResult; deferredResult = new Clipperz.Async.Deferred("User.hasAnyCleanTextData", {trace:false}); deferredResult.collectResults({ 'header': [ MochiKit.Base.method(this, 'invokeMethodNamedOnHeader', 'hasAnyCleanTextData'), MochiKit.Base.values ], 'records': MochiKit.Base.method(this, 'invokeMethodNamedOnRecords', 'hasAnyCleanTextData'), 'data': MochiKit.Base.bind(function () { return MochiKit.Async.succeed(! this.data().isEmpty()); }, this), 'transientState': MochiKit.Base.bind(function () { return MochiKit.Async.succeed(MochiKit.Base.keys(this.transientState()).length != 0); }, this) }); deferredResult.addCallback(Clipperz.Async.or); deferredResult.callback(); return deferredResult; }, //========================================================================= 'prepareRemoteDataWithKey': function (aKey /*, aCurrentKey*/) { var deferredResult; var result; result = {}; deferredResult = new Clipperz.Async.Deferred("User.prepareRemoteDataWithKey", {trace:false}); deferredResult.addMethod(this, 'invokeMethodNamedOnHeader', 'prepareRemoteDataWithKey', aKey /*, aCurrentKey*/); deferredResult.addCallback(MochiKit.Base.bind(function (aResult, someHeaderPackedData) { var header; header = {}; header['records'] = someHeaderPackedData['recordIndex']['records']; header['directLogins'] = someHeaderPackedData['recordIndex']['directLogins']; header['preferences'] = {'data': someHeaderPackedData['preferences']['data']}; // this._serverData['header']['preferences']; // Clipperz.Base.evalJSON(this._serverData['header']['data'])['preferences']; // ??????????? header['oneTimePasswords'] = {'data': someHeaderPackedData['oneTimePasswords']['data']}; // this._serverData['header']['oneTimePasswords']; // Clipperz.Base.evalJSON(this._serverData['header']['data'])['oneTimePasswords']; // ??????????? header['version'] = '0.1'; aResult['header'] = Clipperz.Base.serializeJSON(header); aResult['statistics'] = this._serverData['statistics']; // "someHeaderPackedData['statistics']['data']"; return aResult; }, this), result); deferredResult.addCallback(Clipperz.Async.setItem, result, 'version', Clipperz.PM.Crypto.encryptingFunctions.currentVersion); // deferredResult.addCallback(Clipperz.Async.setItem, result, 'lock', this.serverLockValue()); deferredResult.callback(); return deferredResult; }, //========================================================================= 'saveChanges': function () { var deferredResult; var messageParameters; messageParameters = {}; deferredResult = new Clipperz.Async.Deferred("User.saveChangaes", {trace:false}); deferredResult.addMethod(this, 'getHeaderIndex', 'recordsIndex'); deferredResult.addCallback(MochiKit.Base.methodcaller('prepareRemoteDataForChangedRecords')); deferredResult.addCallback(Clipperz.Async.setItem, messageParameters, 'records'); deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress'); deferredResult.addMethod(this, 'getPassphrase'); deferredResult.addMethod(this, 'prepareRemoteDataWithKey'); deferredResult.addCallback(Clipperz.Async.setItem, messageParameters, 'user'); deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress'); deferredResult.addCallback(MochiKit.Async.succeed, messageParameters); deferredResult.addMethod(this.connection(), 'message', 'saveChanges'); deferredResult.addCallback(MochiKit.Base.update, this.transientState()) deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress'); deferredResult.addMethod(this, 'commitTransientState'); deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress'); deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'userDataSuccessfullySaved'); deferredResult.addErrbackPass(MochiKit.Base.method(this, 'revertChanges')); deferredResult.addErrbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'failureWhileSavingUserData'); deferredResult.callback(); return deferredResult; }, //========================================================================= __syntaxFix__: "syntax fix" }); //----------------------------------------------------------------------------- Clipperz.PM.DataModel.User.registerNewAccount = function (anUsername, aPassphraseFunction) { var deferredResult; var user; user = new Clipperz.PM.DataModel.User({'username':anUsername, 'getPassphraseFunction':aPassphraseFunction}); deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.User.registerNewAccount", {trace:false}); deferredResult.addMethod(user, 'registerAsNewAccount'); deferredResult.addMethod(user, 'login'); deferredResult.addCallback(MochiKit.Async.succeed, user); deferredResult.callback(); return deferredResult; |