summaryrefslogtreecommitdiff
path: root/frontend/delta/js/Clipperz/PM/DataModel/User.js
Unidiff
Diffstat (limited to 'frontend/delta/js/Clipperz/PM/DataModel/User.js') (more/less context) (ignore whitespace changes)
-rw-r--r--frontend/delta/js/Clipperz/PM/DataModel/User.js827
1 files changed, 827 insertions, 0 deletions
diff --git a/frontend/delta/js/Clipperz/PM/DataModel/User.js b/frontend/delta/js/Clipperz/PM/DataModel/User.js
new file mode 100644
index 0000000..1d90800
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/PM/DataModel/User.js
@@ -0,0 +1,827 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
25if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
26if (typeof(Clipperz.PM.DataModel) == 'undefined') { Clipperz.PM.DataModel = {}; }
27
28
29//#############################################################################
30
31Clipperz.PM.DataModel.User = function (args) {
32 args = args || {};
33
34 Clipperz.PM.DataModel.User.superclass.constructor.apply(this, arguments);
35
36 this._username = args.username || null;
37 this._getPassphraseFunction = args.getPassphraseFunction || null;
38
39 this._data = null;
40
41 this._connection = null;
42 this._connectionVersion = 'current';
43
44 this._subscription = null;
45 this._serverData = null;
46 //this._serverLockValue = null;
47 this._transientState = null;
48
49 this._deferredLocks = {
50 'passphrase': new MochiKit.Async.DeferredLock(),
51 'serverData': new MochiKit.Async.DeferredLock(),
52 // 'recordsIndex': new MochiKit.Async.DeferredLock(),
53 // 'directLoginsIndex':new MochiKit.Async.DeferredLock()
54 // 'preferences': new MochiKit.Async.DeferredLock()
55 // 'oneTimePasswords': new MochiKit.Async.DeferredLock()
56 '__syntaxFix__': 'syntax fix'
57 };
58
59 return this;
60}
61
62Clipperz.Base.extend(Clipperz.PM.DataModel.User, Object, {
63
64 'toString': function () {
65 return "Clipperz.PM.DataModel.User - " + this.username();
66 },
67
68 //-------------------------------------------------------------------------
69
70 'username': function () {
71 return this._username;
72 },
73
74 'setUsername': function (aValue) {
75 this._username = aValue;
76 },
77
78 //-------------------------------------------------------------------------
79
80 //this.setSubscription(new Clipperz.PM.DataModel.User.Subscription(someServerData['subscription']));
81 'subscription': function () {
82 return this._subscription;
83 },
84
85 'setSubscription': function (aValue) {
86 this._subscription = aValue;
87 },
88
89 //-------------------------------------------------------------------------
90
91 'displayName': function() {
92 return "" + this.username() + "";
93 },
94
95 //-------------------------------------------------------------------------
96
97 'data': function () {
98 if (this._data == null) {
99 this._data = new Clipperz.KeyValueObjectStore(/*{'name':'User.data [1]'}*/);
100 };
101
102 return this._data;
103 },
104
105 //-------------------------------------------------------------------------
106/*
107 'serverLockValue': function () {
108 return this._serverLockValue;
109 },
110
111 'setServerLockValue': function (aValue) {
112 this._serverLockValue = aValue;
113 },
114*/
115 //-------------------------------------------------------------------------
116
117 'transientState': function () {
118 if (this._transientState == null) {
119 this._transientState = {}
120 }
121
122 return this._transientState;
123 },
124
125 'resetTransientState': function (isCommitting) {
126 this._transientState = null;
127 },
128
129 //-------------------------------------------------------------------------
130
131 'deferredLockForSection': function(aSectionName) {
132 return this._deferredLocks[aSectionName];
133 },
134
135 //-------------------------------------------------------------------------
136
137 'getPassphrase': function() {
138 var deferredResult;
139
140 deferredResult = new Clipperz.Async.Deferred("User.getPassphrase", {trace:false});
141 deferredResult.acquireLock(this.deferredLockForSection('passphrase'));
142 deferredResult.addMethod(this.data(), 'deferredGetOrSet', 'passphrase', this.getPassphraseFunction());
143 deferredResult.releaseLock(this.deferredLockForSection('passphrase'));
144 deferredResult.callback();
145
146 return deferredResult;
147 },
148
149 'getPassphraseFunction': function () {
150 return this._getPassphraseFunction;
151 },
152
153 //-------------------------------------------------------------------------
154
155 'getCredentials': function () {
156 return Clipperz.Async.collectResults("User; get username and passphrase", {
157 'username': MochiKit.Base.method(this, 'username'),
158 'password': MochiKit.Base.method(this, 'getPassphrase')
159 }, {trace:false})();
160 },
161
162 //-------------------------------------------------------------------------
163
164 'changePassphrase': function (aNewValue) {
165 return this.updateCredentials(this.username(), aNewValue);
166 },
167
168 //.........................................................................
169
170 'updateCredentials': function (aUsername, aPassphrase) {
171 vardeferredResult;
172
173 deferredResult = new Clipperz.Async.Deferred("User.updateCredentials", {trace:false});
174 // deferredResult.addMethod(this, 'getPassphrase');
175 // deferredResult.setValue('currentPassphrase');
176 deferredResult.addMethod(this.connection(), 'ping');
177 deferredResult.addMethod(this, 'setUsername', aUsername)
178 deferredResult.acquireLock(this.deferredLockForSection('passphrase'));
179 deferredResult.addMethod(this.data(), 'deferredGetOrSet', 'passphrase', aPassphrase);
180 deferredResult.releaseLock(this.deferredLockForSection('passphrase'));
181 // deferredResult.getValue('currentPassphrase');
182 deferredResult.addMethod(this, 'prepareRemoteDataWithKey', aPassphrase);
183 deferredResult.addMethod(this.connection(), 'updateCredentials', aUsername, aPassphrase);
184 deferredResult.callback();
185
186 return deferredResult;
187 },
188
189 //-------------------------------------------------------------------------
190
191 'initialSetupWithNoData': function () {
192 this._serverData = {
193 'version': '0.1',
194 'statistics': "",
195 'header': {
196 'data': null,
197 'version': Clipperz.PM.Crypto.encryptingFunctions.currentVersion,
198
199 'recordsIndex': new Clipperz.PM.DataModel.User.Header.RecordIndex({
200 'retrieveKeyFunction': MochiKit.Base.method(this, 'getPassphrase'),
201 'recordsData': {'data':null, 'index':{}},
202 'recordsStats': null,
203 'directLoginsData': {'data':null, 'index':{}},
204 'encryptedDataVersion': Clipperz.PM.Crypto.encryptingFunctions.currentVersion,
205 'retrieveRecordDetailFunction':MochiKit.Base.method(this, 'getRecordDetail')
206 }),
207 'preferences': new Clipperz.PM.DataModel.User.Header.Preferences({
208 'name':'preferences',
209 'retrieveKeyFunction': MochiKit.Base.method(this, 'getPassphrase')
210 }),
211 'oneTimePasswords': new Clipperz.PM.DataModel.User.Header.OneTimePasswords({
212 'name':'preferences',
213 'retrieveKeyFunction': MochiKit.Base.method(this, 'getPassphrase')
214 })
215 }
216 };
217
218 // this._serverLockValue = Clipperz.PM.Crypto.randomKey();
219 },
220
221 //.........................................................................
222
223 'registerAsNewAccount': function () {
224 var deferredResult;
225
226 deferredResult = new Clipperz.Async.Deferred("User.registerAsNewAccount", {trace:false});
227 // deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'updateProgress', {'extraSteps':3});
228 deferredResult.addMethod(this, 'initialSetupWithNoData')
229 deferredResult.addMethod(this, 'getPassphrase');
230 deferredResult.addMethod(this, 'prepareRemoteDataWithKey');
231 // deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
232 deferredResult.addMethod(this.connection(), 'register');
233 // deferredResult.addCallback(MochiKit.Base.itemgetter('lock'));
234 // deferredResult.addMethod(this, 'setServerLockValue');
235 // deferredResult.addCallbackPass(MochiKit.Signal.signal,Clipperz.Signal.NotificationCenter, 'userSuccessfullyRegistered');
236
237 // deferredResult.addErrback (MochiKit.Base.method(this, 'handleRegistrationFailure'));
238
239 deferredResult.callback();
240
241 return deferredResult;
242 },
243
244 //-------------------------------------------------------------------------
245
246 'login': function () {
247 var deferredResult;
248
249 deferredResult = new Clipperz.Async.Deferred("User.login", {trace:false});
250 // deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'updateProgress', {'extraSteps':3});
251 deferredResult.addMethod(this, 'getPassphrase');
252 deferredResult.addCallback(Clipperz.PM.DataModel.OneTimePassword.isValidOneTimePasswordValue);
253 deferredResult.addCallback(Clipperz.Async.deferredIf("Is the passphrase an OTP", [
254 // MochiKit.Base.partial(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'updateProgress', {'extraSteps':1}),
255 MochiKit.Base.method(this, 'getCredentials'),
256 MochiKit.Base.method(this.connection(), 'redeemOneTimePassword'),
257 MochiKit.Base.method(this.data(), 'setValue', 'passphrase')
258 ], []));
259 deferredResult.addErrback(MochiKit.Base.method(this, 'getPassphrase'));
260 deferredResult.addMethod(this.connection(), 'login', false);
261 deferredResult.addMethod(this, 'setupConnectionInfo');
262 // deferredResult.addCallbackPass(MochiKit.Signal.signal,Clipperz.Signal.NotificationCenter, 'userSuccessfullyLoggedIn');
263 deferredResult.addErrback (MochiKit.Base.method(this, 'handleConnectionFallback'));
264
265 deferredResult.callback();
266
267 return deferredResult;
268 },
269
270 //.........................................................................
271
272 'handleConnectionFallback': function(aValue) {
273 var result;
274
275//console.log("USER - handleConnectionFallback", aValue, aValue['isPermanent']);
276 if (aValue instanceof MochiKit.Async.CancelledError) {
277 result = aValue;
278 } else if ((aValue['isPermanent'] === true) || (Clipperz.PM.Connection.communicationProtocol.fallbackVersions[this.connectionVersion()] == null)) {
279 result = Clipperz.Async.callbacks("User.handleConnectionFallback - failed", [
280 MochiKit.Base.method(this.data(), 'removeValue', 'passphrase'),
281 MochiKit.Base.method(this, 'setConnectionVersion', 'current'),
282 // MochiKit.Base.partial(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'userLoginFailed'),
283 // MochiKit.Base.partial(MochiKit.Async.fail, Clipperz.PM.DataModel.User.exception.LoginFailed)
284 MochiKit.Base.partial(MochiKit.Async.fail, aValue)
285 ], {trace:false});
286 } else {
287 this.setConnectionVersion(Clipperz.PM.Connection.communicationProtocol.fallbackVersions[this.connectionVersion()]);
288 result = new Clipperz.Async.Deferred("User.handleConnectionFallback - retry");
289 result.addMethod(this, 'login');
290 result.callback();
291 }
292
293 return result;
294 },
295
296 //-------------------------------------------------------------------------
297
298 'setupConnectionInfo': function (aValue) {
299 // this.setLoginInfo(aValue['loginInfo']);
300 this.setSubscription(new Clipperz.PM.DataModel.User.Subscription(aValue['subscription']));
301 },
302
303 //-------------------------------------------------------------------------
304
305 'lock': function () {
306 return Clipperz.Async.callbacks("User.lock", [
307 MochiKit.Base.method(this, 'deleteAllCleanTextData')
308 ], {trace:false});
309 },
310
311 //-------------------------------------------------------------------------
312
313 'logout': function () {
314 return Clipperz.Async.callbacks("User.logout", [
315 MochiKit.Base.method(this, 'deleteAllCleanTextData'),
316 MochiKit.Base.method(this.connection(), 'logout')
317 ], {trace:false});
318 },
319
320 //-------------------------------------------------------------------------
321
322 'headerFormatVersion': function(anHeader) {
323 var result;
324
325 if (anHeader.charAt(0) == '{') {
326 varheaderData;
327
328 headerData = Clipperz.Base.evalJSON(anHeader);
329 result = headerData['version'];
330 } else {
331 result = 'LEGACY';
332 }
333
334 return result;
335 },
336
337 //-------------------------------------------------------------------------
338
339 'unpackServerData': function (someServerData) {
340 var unpackedData;
341 var headerVersion;
342
343 varrecordsIndex;
344 var preferences;
345 var oneTimePasswords;
346
347 // this.setServerLockValue(someServerData['lock']);
348
349 headerVersion = this.headerFormatVersion(someServerData['header']);
350 switch (headerVersion) {
351 case 'LEGACY':
352 varlegacyHeader;
353
354 legacyHeader = new Clipperz.PM.DataModel.User.Header.Legacy({
355 'retrieveKeyFunction': MochiKit.Base.method(this, 'getPassphrase'),
356 'remoteData': {
357 'data': someServerData['header'],
358 'version': someServerData['version'],
359 'recordsStats': someServerData['recordsStats']
360 },
361 // 'encryptedDataKeypath': 'data',
362 // 'encryptedVersionKeypath': 'version',
363 'retrieveRecordDetailFunction':MochiKit.Base.method(this, 'getRecordDetail')
364 });
365
366 recordsIndex = legacyHeader;
367 preferences = legacyHeader;
368 oneTimePasswords= legacyHeader;
369 break;
370 case '0.1':
371 varheaderData;
372
373 headerData = Clipperz.Base.evalJSON(someServerData['header']);
374
375 recordsIndex = new Clipperz.PM.DataModel.User.Header.RecordIndex({
376 'retrieveKeyFunction': MochiKit.Base.method(this, 'getPassphrase'),
377 'recordsData': headerData['records'],
378 'recordsStats': someServerData['recordsStats'],
379 'directLoginsData': headerData['directLogins'],
380 'encryptedDataVersion': someServerData['version'],
381 'retrieveRecordDetailFunction':MochiKit.Base.method(this, 'getRecordDetail')
382 });
383
384 //Still missing a test case that actually fais with the old version of the code, where the check for undefined was missing
385 if (typeof(headerData['preferences']) != 'undefined') {
386 preferences= new Clipperz.PM.DataModel.User.Header.Preferences({
387 'name':'preferences',
388 'retrieveKeyFunction': MochiKit.Base.method(this, 'getPassphrase'),
389 'remoteData': {
390 'data': headerData['preferences']['data'],
391 'version': someServerData['version']
392 }
393 });
394 } else {
395 preferences= new Clipperz.PM.DataModel.User.Header.Preferences({
396 'name':'preferences',
397 'retrieveKeyFunction': MochiKit.Base.method(this, 'getPassphrase')
398 });
399 }
400
401 if (typeof(headerData['oneTimePasswords']) != 'undefined') {
402 oneTimePasswords = new Clipperz.PM.DataModel.User.Header.OneTimePasswords({
403 'name':'preferences',
404 'retrieveKeyFunction': MochiKit.Base.method(this, 'getPassphrase'),
405 'remoteData': {
406 'data': headerData['oneTimePasswords']['data'],
407 'version': someServerData['version']
408 }
409 });
410 } else {
411 oneTimePasswords = new Clipperz.PM.DataModel.User.Header.OneTimePasswords({
412 'name':'preferences',
413 'retrieveKeyFunction': MochiKit.Base.method(this, 'getPassphrase')
414 });
415 }
416
417 break;
418 }
419
420 unpackedData = {
421 'version': someServerData['version'],
422 'statistics': someServerData['statistics'],
423 'header': {
424 'data': someServerData['header'],
425 'version': headerVersion,
426
427 'recordsIndex': recordsIndex,
428 'preferences': preferences,
429 'oneTimePasswords': oneTimePasswords
430 }
431 };
432
433 this._serverData = unpackedData;
434
435 return this._serverData;
436 },
437
438 //-------------------------------------------------------------------------
439
440 'getServerData': function() {
441 var deferredResult;
442
443 deferredResult = new Clipperz.Async.Deferred("User.getServerData", {trace:false});
444 deferredResult.acquireLock(this.deferredLockForSection('serverData'));
445 deferredResult.addCallback(MochiKit.Base.bind(function(aResult) {
446 var innerDeferredResult;
447
448 innerDeferredResult = new Clipperz.Async.Deferred("User.getUserDetails.innerDeferred", {trace:false});
449 if (this._serverData == null) {
450 innerDeferredResult.addCallbackPass(MochiKit.Signal.signal, this, 'loadingUserDetails');
451 innerDeferredResult.addMethod(this.connection(), 'message', 'getUserDetails');
452 innerDeferredResult.addMethod(this, 'unpackServerData');
453 innerDeferredResult.addCallbackPass(MochiKit.Signal.signal, this, 'loadedUserDetails');
454 }
455
456 innerDeferredResult.addCallback(MochiKit.Base.bind(function () {
457 return this._serverData;
458 },this));
459 innerDeferredResult.callback();
460
461 return innerDeferredResult;
462 }, this));
463 deferredResult.releaseLock(this.deferredLockForSection('serverData'));
464 deferredResult.callback();
465
466 return deferredResult;
467 },
468
469 //-------------------------------------------------------------------------
470
471 'connectionVersion': function() {
472 return this._connectionVersion;
473 },
474
475 'setConnectionVersion': function(aValue) {
476 if (this._connectionVersion != aValue) {
477 this.resetConnection();
478 }
479 this._connectionVersion = aValue;
480 },
481
482 //-------------------------------------------------------------------------
483
484 'connection': function() {
485 if ((this._connection == null) && (this.connectionVersion() != null) ){
486 this._connection = new Clipperz.PM.Connection.communicationProtocol.versions[this.connectionVersion()]({
487 getCredentialsFunction: MochiKit.Base.method(this, 'getCredentials')
488 });
489 }
490
491 return this._connection;
492 },
493
494 'resetConnection': function(aValue) {
495 if (this._connection != null) {
496 this._connection.reset();
497 }
498
499 this._connection = null;
500 },
501
502 //=========================================================================
503
504 'getHeaderIndex': function (aKey) {
505 return Clipperz.Async.callbacks("User.getHeaderIndex", [
506 MochiKit.Base.method(this, 'getServerData'),
507 MochiKit.Base.itemgetter('header'),
508 MochiKit.Base.itemgetter(aKey)
509 ], {trace:false})
510 },
511
512 //=========================================================================
513
514 'getRecords': function () {
515 return Clipperz.Async.callbacks("User.getRecords", [
516 MochiKit.Base.method(this, 'getHeaderIndex', 'recordsIndex'),
517 MochiKit.Base.methodcaller('records'),
518 MochiKit.Base.values
519 ], {trace:false});
520 },
521
522 'recordWithLabel': function (aLabel) {
523 return Clipperz.Async.callbacks("User.recordWithLabel", [
524 MochiKit.Base.method(this, 'getRecords'),
525 MochiKit.Base.partial(Clipperz.Async.deferredFilter, function (aRecord) {
526 return Clipperz.Async.callbacks("User.recordWithLabel - check record label", [
527 MochiKit.Base.methodcaller('label'),
528 MochiKit.Base.partial(MochiKit.Base.operator.eq, aLabel)
529 ], {trace:false}, aRecord);
530 }),
531 function (someFilteredResults) {
532 var result;
533
534 switch (someFilteredResults.length) {
535 case 0:
536 result = null;
537 break;
538 case 1:
539 result = someFilteredResults[0];
540 break;
541 default:
542 WTF = TODO;
543 break;
544 }
545
546 return result;
547 }
548 ], {trace:false});
549 },
550
551 //-------------------------------------------------------------------------
552
553 'getRecord': function (aRecordReference) {
554 return Clipperz.Async.callbacks("User.getRecord", [
555 MochiKit.Base.method(this, 'getHeaderIndex', 'recordsIndex'),
556 MochiKit.Base.methodcaller('records'),
557 MochiKit.Base.itemgetter(aRecordReference),
558
559 Clipperz.Async.deferredIf("record != null", [
560 MochiKit.Base.operator.identity
561 ], [
562 function () { throw "Record does not exists"}
563 ])
564 ], {trace:false});
565 },
566
567 //-------------------------------------------------------------------------
568
569 'getRecordDetail': function (aRecordReference) {
570 return this.connection().message('getRecordDetail', {reference: aRecordReference});
571 },
572
573 //-------------------------------------------------------------------------
574
575 'deleteRecord': function (aRecord) {
576 return Clipperz.Async.callbacks("User.deleteRecord", [
577 MochiKit.Base.method(this, 'getHeaderIndex', 'recordsIndex'),
578 MochiKit.Base.methodcaller('deleteRecord', aRecord)
579 ], {trace:false});
580 },
581
582 //-------------------------------------------------------------------------
583
584 'createNewRecord': function () {
585 return Clipperz.Async.callbacks("User.createNewRecord", [
586 MochiKit.Base.method(this, 'getHeaderIndex', 'recordsIndex'),
587 MochiKit.Base.methodcaller('createNewRecord')
588 ], {trace:false});
589 },
590
591 //=========================================================================
592
593 'getDirectLogins': function() {
594 var deferredResult;
595
596 deferredResult = new Clipperz.Async.Deferred("User.getDirectLogins", {trace:false});
597 deferredResult.addMethod(this, 'getRecords');
598 deferredResult.addCallback(MochiKit.Base.map, MochiKit.Base.compose(MochiKit.Base.values, MochiKit.Base.methodcaller('directLogins')));
599 deferredResult.addCallback(MochiKit.Base.flattenArray);
600 deferredResult.callback();
601
602 return deferredResult;
603 },
604
605 //=========================================================================
606
607 'getOneTimePasswords': function () {
608 return Clipperz.Async.callbacks("User.getOneTimePasswords", [
609 MochiKit.Base.method(this, 'getHeaderIndex', 'oneTimePasswords'),
610 MochiKit.Base.methodcaller('oneTimePasswords'),
611 MochiKit.Base.values
612 ], {trace:false});
613 },
614
615 //=========================================================================
616
617 'invokeMethodNamedOnHeader': function (aMethodName, aValue) {
618 return Clipperz.Async.collectResults("User.invokeMethodNamedOnHeader [" + aMethodName + "]", {
619 'recordIndex': [
620 MochiKit.Base.method(this, 'getHeaderIndex', 'recordsIndex'),
621 MochiKit.Base.methodcaller(aMethodName, aValue)
622 ],
623 'preferences': [
624 MochiKit.Base.method(this, 'getHeaderIndex', 'preferences'),
625 MochiKit.Base.methodcaller(aMethodName, aValue)
626 ],
627 'oneTimePasswords': [
628 MochiKit.Base.method(this, 'getHeaderIndex', 'oneTimePasswords'),
629 MochiKit.Base.methodcaller(aMethodName, aValue)
630 ]//,
631 // 'statistics': [
632 // MochiKit.Base.method(this, 'getStatistics'),
633 // MochiKit.Base.methodcaller(aMethodName, aValue)
634 // ]
635 }, {trace:false})();
636 },
637
638 //-------------------------------------------------------------------------
639
640 'invokeMethodNamedOnRecords': function (aMethodName, aValue) {
641 return Clipperz.Async.callbacks("User.invokeMethodNamedOnRecords[" + aMethodName + "]", [
642 MochiKit.Base.method(this, 'getRecords'),
643 MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller(aMethodName, aValue)),
644 Clipperz.Async.collectAll
645 ], {trace:false});
646 },
647
648 //=========================================================================
649
650 'hasPendingChanges': function () {
651 vardeferredResult;
652
653 deferredResult = new Clipperz.Async.Deferred("User.hasPendingChanges", {trace:false});
654 deferredResult.collectResults({
655 'header': [
656 MochiKit.Base.method(this, 'invokeMethodNamedOnHeader', 'hasPendingChanges'),
657 MochiKit.Base.values
658 ],
659 'records': MochiKit.Base.method(this, 'invokeMethodNamedOnRecords', 'hasPendingChanges')
660 });
661 deferredResult.addCallback(Clipperz.Async.or);
662 deferredResult.callback();
663 // recordsIndex = legacyHeader;
664 // preferences = legacyHeader;
665 // oneTimePasswords= legacyHeader;
666
667 return deferredResult;
668 },
669
670 //=========================================================================
671
672 'commitTransientState': function () {
673 return Clipperz.Async.callbacks("User.commitTransientState", [
674 MochiKit.Base.method(this, 'invokeMethodNamedOnHeader', 'commitTransientState'),
675 MochiKit.Base.method(this, 'invokeMethodNamedOnRecords', 'commitTransientState'),
676
677 MochiKit.Base.method(this, 'transientState'),
678 // MochiKit.Base.itemgetter('lock'),
679 // MochiKit.Base.method(this, 'setServerLockValue'),
680 MochiKit.Base.method(this, 'resetTransientState', true)
681 ], {trace:false});
682 },
683
684 //-------------------------------------------------------------------------
685
686 'revertChanges': function () {
687 return Clipperz.Async.callbacks("User.revertChanges", [
688 MochiKit.Base.method(this, 'invokeMethodNamedOnHeader', 'revertChanges'),
689 MochiKit.Base.method(this, 'invokeMethodNamedOnRecords', 'revertChanges'),
690 MochiKit.Base.method(this, 'resetTransientState', false)
691 ], {trace:false});
692 },
693
694 //=========================================================================
695
696 'deleteAllCleanTextData': function () {
697 return Clipperz.Async.callbacks("User.deleteAllCleanTextData", [
698 MochiKit.Base.method(this, 'invokeMethodNamedOnRecords', 'deleteAllCleanTextData'),
699 MochiKit.Base.method(this, 'invokeMethodNamedOnHeader', 'deleteAllCleanTextData'),
700
701 MochiKit.Base.method(this.data(), 'removeAllData'),
702 MochiKit.Base.method(this, 'resetTransientState', false)
703 ], {trace:false});
704 },
705
706 //-------------------------------------------------------------------------
707
708 'hasAnyCleanTextData': function () {
709 vardeferredResult;
710
711 deferredResult = new Clipperz.Async.Deferred("User.hasAnyCleanTextData", {trace:false});
712 deferredResult.collectResults({
713 'header':[
714 MochiKit.Base.method(this, 'invokeMethodNamedOnHeader', 'hasAnyCleanTextData'),
715 MochiKit.Base.values
716 ],
717 'records':MochiKit.Base.method(this, 'invokeMethodNamedOnRecords', 'hasAnyCleanTextData'),
718 'data': MochiKit.Base.bind(function () {
719 return MochiKit.Async.succeed(! this.data().isEmpty());
720 }, this),
721 'transientState':MochiKit.Base.bind(function () {
722 return MochiKit.Async.succeed(MochiKit.Base.keys(this.transientState()).length != 0);
723 }, this)
724 });
725 deferredResult.addCallback(Clipperz.Async.or);
726 deferredResult.callback();
727
728 return deferredResult;
729 },
730
731 //=========================================================================
732
733 'prepareRemoteDataWithKey': function (aKey /*, aCurrentKey*/) {
734 var deferredResult;
735 varresult;
736
737 result = {};
738 deferredResult = new Clipperz.Async.Deferred("User.prepareRemoteDataWithKey", {trace:false});
739 deferredResult.addMethod(this, 'invokeMethodNamedOnHeader', 'prepareRemoteDataWithKey', aKey /*, aCurrentKey*/);
740 deferredResult.addCallback(MochiKit.Base.bind(function (aResult, someHeaderPackedData) {
741 var header;
742
743 header = {};
744 header['records'] = someHeaderPackedData['recordIndex']['records'];
745 header['directLogins'] = someHeaderPackedData['recordIndex']['directLogins'];
746 header['preferences'] = {'data': someHeaderPackedData['preferences']['data']};
747 header['oneTimePasswords']= {'data': someHeaderPackedData['oneTimePasswords']['data']};
748 header['version'] = '0.1';
749
750 aResult['header'] = Clipperz.Base.serializeJSON(header);
751 aResult['statistics'] = this._serverData['statistics']; //"someHeaderPackedData['statistics']['data']";
752
753 return aResult;
754 }, this), result);
755 deferredResult.addCallback(Clipperz.Async.setItem, result, 'version', Clipperz.PM.Crypto.encryptingFunctions.currentVersion);
756 // deferredResult.addCallback(Clipperz.Async.setItem, result, 'lock', this.serverLockValue());
757 deferredResult.callback();
758
759 return deferredResult;
760 },
761
762 //=========================================================================
763
764 'saveChanges': function () {
765 vardeferredResult;
766 var messageParameters;
767
768 messageParameters = {};
769
770 deferredResult = new Clipperz.Async.Deferred("User.saveChangaes", {trace:false});
771
772 deferredResult.addMethod(this, 'getHeaderIndex', 'recordsIndex');
773 deferredResult.addCallback(MochiKit.Base.methodcaller('prepareRemoteDataForChangedRecords'));
774 deferredResult.addCallback(Clipperz.Async.setItem, messageParameters, 'records');
775 // deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
776
777 deferredResult.addMethod(this, 'getPassphrase');
778 deferredResult.addMethod(this, 'prepareRemoteDataWithKey');
779 deferredResult.addCallback(Clipperz.Async.setItem, messageParameters, 'user');
780 // deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
781
782 deferredResult.addCallback(MochiKit.Async.succeed, messageParameters);
783 deferredResult.addMethod(this.connection(), 'message', 'saveChanges');
784 deferredResult.addCallback(MochiKit.Base.update, this.transientState())
785 // deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
786
787 deferredResult.addMethod(this, 'commitTransientState');
788 // deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
789 // deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'userDataSuccessfullySaved');
790
791 deferredResult.addErrbackPass(MochiKit.Base.method(this, 'revertChanges'));
792 // deferredResult.addErrbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'failureWhileSavingUserData');
793
794 deferredResult.callback();
795
796 return deferredResult;
797 },
798
799 //=========================================================================
800 __syntaxFix__: "syntax fix"
801});
802
803//-----------------------------------------------------------------------------
804
805Clipperz.PM.DataModel.User.registerNewAccount = function (anUsername, aPassphraseFunction) {
806 vardeferredResult;
807 var user;
808
809 user = new Clipperz.PM.DataModel.User({'username':anUsername, 'getPassphraseFunction':aPassphraseFunction});
810
811 deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.User.registerNewAccount", {trace:false});
812 deferredResult.addMethod(user, 'registerAsNewAccount');
813 deferredResult.addMethod(user, 'login');
814 deferredResult.addCallback(MochiKit.Async.succeed, user);
815 deferredResult.callback();
816
817 return deferredResult;
818}
819
820//-----------------------------------------------------------------------------
821
822Clipperz.PM.DataModel.User.exception = {
823 LoginFailed: new MochiKit.Base.NamedError("Clipperz.PM.DataModel.User.exception.LoginFailed"),
824 CredentialUpgradeFailed:new MochiKit.Base.NamedError("Clipperz.PM.DataModel.User.exception.CredentialUpgradeFailed")
825};
826
827//-----------------------------------------------------------------------------