Diffstat (limited to 'frontend/delta/js/Clipperz/PM/DataModel/User.js') (more/less context) (show whitespace changes)
-rw-r--r-- | frontend/delta/js/Clipperz/PM/DataModel/User.js | 827 |
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 | |||
3 | Copyright 2008-2013 Clipperz Srl | ||
4 | |||
5 | This file is part of Clipperz, the online password manager. | ||
6 | For further information about its features and functionalities please | ||
7 | refer 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 | |||
24 | if (typeof(Clipperz) == 'undefined') { Clipperz = {}; } | ||
25 | if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; } | ||
26 | if (typeof(Clipperz.PM.DataModel) == 'undefined') { Clipperz.PM.DataModel = {}; } | ||
27 | |||
28 | |||
29 | //############################################################################# | ||
30 | |||
31 | Clipperz.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 | |||
62 | Clipperz.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 | |||
805 | Clipperz.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 | |||
822 | Clipperz.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 | //----------------------------------------------------------------------------- | ||