/* Copyright 2008-2015 Clipperz Srl 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 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 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. If not, see http://www.gnu.org/licenses/. */ "use strict"; Clipperz.Base.module('Clipperz.PM.DataModel'); //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._accountInfo = null; this._serverData = null; // this._serverLockValue = null; this._transientState = null; this._deferredLocks = { 'passphrase': new MochiKit.Async.DeferredLock(), 'serverData': new MochiKit.Async.DeferredLock(), '__syntaxFix__': 'syntax fix' }; this._usedOTP = null; 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; }, //------------------------------------------------------------------------- 'setUsedOTP': function(aOTP) { this._usedOTP = aOTP; return aOTP; }, 'resetUsedOTP': function(aOTP) { this._usedOTP = null; }, 'markUsedOTP': function(aOTP) { var result; var oneTimePasswordKey; if (this._usedOTP) { oneTimePasswordKey = Clipperz.PM.DataModel.OneTimePassword.computeKeyWithPassword( Clipperz.PM.DataModel.OneTimePassword.normalizedOneTimePassword(this._usedOTP) ); result = Clipperz.Async.callbacks("User.markUsedOTP", [ // NOTE: fired also when passphrase looks exactly like OTP MochiKit.Base.method(this, 'getHeaderIndex', 'oneTimePasswords'), MochiKit.Base.methodcaller('markOTPAsUsed', oneTimePasswordKey), MochiKit.Base.method(this,'saveChanges'), // Too 'heavy'? MochiKit.Base.method(this, 'resetUsedOTP') ], {'trace': false}); } else { result = MochiKit.Async.succeed(); } return result; }, //------------------------------------------------------------------------- // this.setSubscription(new Clipperz.PM.DataModel.User.Subscription(someServerData['subscription'])); 'accountInfo': function () { return this._accountInfo; }, 'setAccountInfo': function (aValue) { this._accountInfo = 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() { return this._getPassphraseFunction(); }, 'getPassphraseFunction': function () { return this._getPassphraseFunction; }, 'setPassphraseFunction': function (aFunction) { this._getPassphraseFunction = aFunction; }, //------------------------------------------------------------------------- '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 (aNewValueCallback) { return this.updateCredentials(this.username(), aNewValueCallback); }, //......................................................................... 'updateCredentials': function (aUsername, aPassphraseCallback) { var deferredResult; deferredResult = new Clipperz.Async.Deferred("User.updateCredentials", {trace:false}); deferredResult.addMethod(this.connection(), 'ping'); deferredResult.collectResults({ 'newUsername': MochiKit.Base.partial(MochiKit.Async.succeed, aUsername), 'newPassphrase': aPassphraseCallback, 'user': MochiKit.Base.method(this, 'prepareRemoteDataWithKeyFunction', aPassphraseCallback), 'oneTimePasswords': [ MochiKit.Base.method(this, 'getHeaderIndex', 'oneTimePasswords'), MochiKit.Base.methodcaller('getEncryptedOTPData', aPassphraseCallback), function (otps) { var result; var otpRefs; var i, c; result = {}; otpRefs = MochiKit.Base.keys(otps); c = otpRefs.length; for (i=0; i