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