Diffstat (limited to 'frontend/delta/js/Clipperz/PM/DataModel') (more/less context) (ignore whitespace changes)
15 files changed, 5708 insertions, 0 deletions
diff --git a/frontend/delta/js/Clipperz/PM/DataModel/DirectLogin.js b/frontend/delta/js/Clipperz/PM/DataModel/DirectLogin.js new file mode 100644 index 0000000..8db90de --- a/dev/null +++ b/frontend/delta/js/Clipperz/PM/DataModel/DirectLogin.js | |||
@@ -0,0 +1,1086 @@ | |||
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 | Clipperz.Base.module('Clipperz.PM.DataModel'); | ||
25 | |||
26 | Clipperz.PM.DataModel.DirectLogin = function(args) { | ||
27 | args = args || {}; | ||
28 | |||
29 | Clipperz.PM.DataModel.DirectLogin.superclass.constructor.apply(this, arguments); | ||
30 | |||
31 | this._reference =args.reference | ||
32 | ||Clipperz.PM.Crypto.randomKey(); | ||
33 | this._record =args.record | ||
34 | ||Clipperz.Base.exception.raise('MandatoryParameter'); | ||
35 | |||
36 | this._retrieveIndexDataFunction = args.retrieveIndexDataFunction | ||
37 | ||this.record().retrieveDirectLoginIndexDataFunction() | ||
38 | ||Clipperz.Base.exception.raise('MandatoryParameter'); | ||
39 | this._setIndexDataFunction = args.setIndexDataFunction | ||
40 | ||this.record().setDirectLoginIndexDataFunction() | ||
41 | ||Clipperz.Base.exception.raise('MandatoryParameter'); | ||
42 | this._removeIndexDataFunction =args.removeIndexDataFunction | ||
43 | ||this.record().removeDirectLoginIndexDataFunction() | ||
44 | ||Clipperz.Base.exception.raise('MandatoryParameter'); | ||
45 | |||
46 | this._inputs = null; | ||
47 | this._bindings = null; | ||
48 | this._formValues = null; | ||
49 | |||
50 | // this._inputsDeferredLock = new MochiKit.Async.DeferredLock(); | ||
51 | // this._bindingsDeferredLock = new MochiKit.Async.DeferredLock(); | ||
52 | // this._formValuesDeferredLock = new MochiKit.Async.DeferredLock(); | ||
53 | |||
54 | this._transientState = null; | ||
55 | |||
56 | this._isBrandNew = MochiKit.Base.isUndefinedOrNull(args.reference); | ||
57 | |||
58 | this.record().addDirectLogin(this); | ||
59 | |||
60 | return this; | ||
61 | } | ||
62 | |||
63 | Clipperz.Base.extend(Clipperz.PM.DataModel.DirectLogin, Object, { | ||
64 | |||
65 | 'toString': function() { | ||
66 | return "DirectLogin (" + this.reference() + ")"; | ||
67 | }, | ||
68 | |||
69 | //========================================================================= | ||
70 | |||
71 | 'reference': function () { | ||
72 | return this._reference; | ||
73 | }, | ||
74 | |||
75 | //------------------------------------------------------------------------- | ||
76 | |||
77 | 'record': function () { | ||
78 | return this._record; | ||
79 | }, | ||
80 | |||
81 | //========================================================================= | ||
82 | |||
83 | 'isBrandNew': function () { | ||
84 | return this._isBrandNew; | ||
85 | }, | ||
86 | |||
87 | //========================================================================= | ||
88 | |||
89 | 'removeIndexDataFunction': function () { | ||
90 | return this._removeIndexDataFunction; | ||
91 | }, | ||
92 | |||
93 | 'remove': function () { | ||
94 | return Clipperz.Async.callbacks("DirectLogin.remove", [ | ||
95 | MochiKit.Base.partial(this.removeIndexDataFunction(), this.reference()), | ||
96 | MochiKit.Base.method(this.record(), 'removeDirectLogin', this) | ||
97 | ], {trace:false}); | ||
98 | }, | ||
99 | |||
100 | //========================================================================= | ||
101 | /* | ||
102 | 'inputsDeferredLock': function () { | ||
103 | return this._inputsDeferredLock; | ||
104 | }, | ||
105 | |||
106 | 'bindingsDeferredLock': function () { | ||
107 | return this._bindingsDeferredLock; | ||
108 | }, | ||
109 | |||
110 | 'formValuesDeferredLock': function () { | ||
111 | return this._formValuesDeferredLock; | ||
112 | }, | ||
113 | */ | ||
114 | //========================================================================= | ||
115 | |||
116 | 'label': function () { | ||
117 | return this.getIndexDataForKey('label'); | ||
118 | }, | ||
119 | |||
120 | 'setLabelKeepingBackwardCompatibilityWithBeta': function (aValue) { | ||
121 | return Clipperz.Async.callbacks("DirectLogin.setLabelKeepingBackwardCompatibilityWithBeta", [ | ||
122 | MochiKit.Base.method(this, 'setIndexDataForKey', 'label', aValue), | ||
123 | MochiKit.Base.method(this, 'setValue', 'label', aValue) | ||
124 | ], {trace:false}); | ||
125 | }, | ||
126 | |||
127 | 'setLabel': function (aValue) { | ||
128 | return this.setLabelKeepingBackwardCompatibilityWithBeta(aValue); | ||
129 | // return this.setIndexDataForKey('label', aValue); | ||
130 | }, | ||
131 | |||
132 | //========================================================================= | ||
133 | |||
134 | 'favicon': function () { | ||
135 | return this.getIndexDataForKey('favicon'); | ||
136 | }, | ||
137 | |||
138 | 'setFavicon': function (aValue) { | ||
139 | return this.setIndexDataForKey('favicon', aValue); | ||
140 | }, | ||
141 | |||
142 | 'faviconUrlWithBookmarkletConfiguration': function (aBookmarkletConfiguration) { | ||
143 | varresult; | ||
144 | |||
145 | if (! MochiKit.Base.isUndefinedOrNull(aBookmarkletConfiguration['page']['favicon'])) { | ||
146 | result = aBookmarkletConfiguration['page']['favicon']; | ||
147 | } else if (! MochiKit.Base.isUndefinedOrNull(aBookmarkletConfiguration['form']['attributes']['action'])) { | ||
148 | var actionUrl; | ||
149 | var hostname; | ||
150 | |||
151 | actionUrl = aBookmarkletConfiguration['form']['attributes']['action']; | ||
152 | hostname = actionUrl.replace(/^https?:\/\/([^\/]*)\/.*/, '$1'); | ||
153 | result = "http://" + hostname + "/favicon.ico"; | ||
154 | } else { | ||
155 | result = null; | ||
156 | } | ||
157 | |||
158 | |||
159 | return result; | ||
160 | }, | ||
161 | |||
162 | //------------------------------------------------------------------------- | ||
163 | /* | ||
164 | 'faviconData': function () { | ||
165 | var regexp = new RegExp('^data\:\/\/.*', 'i'); | ||
166 | |||
167 | return Clipperz.Async.callbacks("DirectLogin.favicon", [ | ||
168 | MochiKit.Base.method(this, 'getIndexDataForKey', 'favicon'), | ||
169 | MochiKit.Base.method(regexp, 'test'), | ||
170 | Clipperz.Async.deferredIf("is data URL", [ | ||
171 | MochiKit.Base.method(this, 'getIndexDataForKey', 'favicon') | ||
172 | ], [ | ||
173 | MochiKit.Base.method(this, 'transientState'), | ||
174 | MochiKit.Base.itemgetter('faviconData'), | ||
175 | Clipperz.Async.deferredIf('has a chaced value for the favicon data', [ | ||
176 | MochiKit.Base.operator.identity | ||
177 | ], [ | ||
178 | MochiKit.Base.method(this, 'getIndexDataForKey', 'favicon'), | ||
179 | MochiKit.Base.method(this, 'loadFaviconDataFromURL') | ||
180 | ]) | ||
181 | |||
182 | ]) | ||
183 | ], {trace:false}); | ||
184 | }, | ||
185 | |||
186 | //------------------------------------------------------------------------- | ||
187 | |||
188 | 'loadFaviconDataFromURL': function (anURL) { | ||
189 | var deferredResult; | ||
190 | var image; | ||
191 | |||
192 | deferredResult = new Clipperz.Async.Deferred("DirectLogin.loadFaviconDataFromURL", {trace:false}); | ||
193 | deferredResult.addCallback(function (anEvent) { | ||
194 | var image = anEvent.src(); | ||
195 | var canvas = document.createElement("canvas"); | ||
196 | var result; | ||
197 | |||
198 | canvas.width = image.width; | ||
199 | canvas.height = image.height; | ||
200 | |||
201 | var ctx = canvas.getContext("2d"); | ||
202 | ctx.drawImage(image, 0, 0); | ||
203 | |||
204 | result = canvas.toDataURL(/*"image/png"* /); | ||
205 | |||
206 | return result; | ||
207 | }); | ||
208 | deferredResult.addErrback(MochiKit.Async.succeed, Clipperz.PM.Strings.getValue('defaultFaviconUrl')); | ||
209 | deferredResult.addBoth(MochiKit.Base.bind(function (aDataUrl) { | ||
210 | this.transientState()['faviconData'] = aDataUrl; | ||
211 | |||
212 | return aDataUrl; | ||
213 | }, this)); | ||
214 | |||
215 | image = new Image(); | ||
216 | MochiKit.Signal.connect(image, 'onload', MochiKit.Base.method(deferredResult, 'callback')); | ||
217 | MochiKit.Signal.connect(image, 'onerror', MochiKit.Base.method(deferredResult, 'errback')); | ||
218 | MochiKit.Signal.connect(image, 'onabort', MochiKit.Base.method(deferredResult, 'errback')); | ||
219 | |||
220 | image.src = anURL; | ||
221 | |||
222 | return deferredResult; | ||
223 | }, | ||
224 | */ | ||
225 | |||
226 | //========================================================================= | ||
227 | |||
228 | 'type': function () { | ||
229 | return this.getValue('formData.attributes.type') | ||
230 | }, | ||
231 | |||
232 | //========================================================================= | ||
233 | |||
234 | 'serializedData': function () { | ||
235 | return Clipperz.Async.collectResults("DirectLogin.serializedData", { | ||
236 | 'bookmarkletVersion': MochiKit.Base.method(this, 'getValue', 'bookmarkletVersion'), | ||
237 | 'formData': MochiKit.Base.method(this, 'getValue', 'formData'), | ||
238 | 'formValues': MochiKit.Base.method(this, 'getValue', 'formValues'), | ||
239 | 'bindingData': [ | ||
240 | MochiKit.Base.method(this, 'bindings'), | ||
241 | function (someBindings) { | ||
242 | var result; | ||
243 | var bindingKey; | ||
244 | |||
245 | result = {} | ||
246 | for (bindingKey in someBindings) { | ||
247 | result[bindingKey] = someBindings[bindingKey].serializedData(); | ||
248 | } | ||
249 | |||
250 | return result; | ||
251 | } | ||
252 | ] | ||
253 | }, {trace:false})() | ||
254 | }, | ||
255 | |||
256 | //========================================================================= | ||
257 | /* | ||
258 | 'fixFormDataFromBookmarkletVersion_0_1': function(aValue) { | ||
259 | //{"type":"radio", "name":"action", "value":"new-user", "checked":false }, { "type":"radio", "name":"action", "value":"sign-in", "checked":true } | ||
260 | // || | ||
261 | // \ / | ||
262 | // \/ | ||
263 | //{"name":"dominio", "type":"radio", "options":[{"value":"@alice.it", "checked":true}, {"value":"@tin.it", "checked":false}, {"value":"@virgilio.it", "checked":false}, {"value":"@tim.it", "checked":false}]} | ||
264 | var result; | ||
265 | var inputs; | ||
266 | var updatedInputs; | ||
267 | var radios; | ||
268 | |||
269 | result = aValue; | ||
270 | inputs = aValue['inputs']; | ||
271 | |||
272 | updatedInputs = MochiKit.Base.filter(function(anInput) { | ||
273 | varresult; | ||
274 | var type; | ||
275 | |||
276 | type = anInput['type'] || 'text'; | ||
277 | result = type.toLowerCase() != 'radio'; | ||
278 | |||
279 | return result; | ||
280 | }, inputs); | ||
281 | radios = MochiKit.Base.filter(function(anInput) { | ||
282 | varresult; | ||
283 | var type; | ||
284 | |||
285 | type = anInput['type'] || 'text'; | ||
286 | result = type.toLowerCase() == 'radio'; | ||
287 | |||
288 | return result; | ||
289 | }, inputs); | ||
290 | |||
291 | if (radios.length > 0) { | ||
292 | var updatedRadios; | ||
293 | |||
294 | updatedRadios = {}; | ||
295 | MochiKit.Iter.forEach(radios, MochiKit.Base.bind(function(aRadio) { | ||
296 | varradioConfiguration; | ||
297 | |||
298 | radioConfiguration = updatedRadios[aRadio['name']]; | ||
299 | if (radioConfiguration == null) { | ||
300 | radioConfiguration = {type:'radio', name:aRadio['name'], options:[]}; | ||
301 | updatedRadios[aRadio['name']] = radioConfiguration; | ||
302 | } | ||
303 | |||
304 | //TODO: remove the value: field and replace it with element.dom.value = <some value> | ||
305 | radioConfiguration.options.push({value:aRadio['value'], checked:aRadio['checked']}); | ||
306 | |||
307 | //TODO: shoud remove the 'formValues' call, as it is now deferred | ||
308 | // if ((aRadio['checked'] == true) && (this.formValues()[aRadio['name']] == null)) { | ||
309 | // this.formValues()[aRadio['name']] = aRadio['value']; | ||
310 | // } | ||
311 | }, this)) | ||
312 | |||
313 | updatedInputs = MochiKit.Base.concat(updatedInputs, MochiKit.Base.values(updatedRadios)); | ||
314 | } | ||
315 | |||
316 | delete result.inputs; | ||
317 | result.inputs = updatedInputs; | ||
318 | |||
319 | return result; | ||
320 | }, | ||
321 | |||
322 | '_fixConfiguration': function (aConfiguration) { | ||
323 | var fixedConfiguration; | ||
324 | // var inputs; | ||
325 | // var bindings; | ||
326 | // var i,c; | ||
327 | |||
328 | fixedConfiguration = Clipperz.Base.deepClone(aConfiguration); | ||
329 | |||
330 | //Clipperz.log("PROCESS CONFIGURATION", aConfiguration); | ||
331 | switch (aConfiguration['bookmarkletVersion']) { | ||
332 | case '0.1': | ||
333 | fixedConfiguration['formData'] = this.fixFormDataFromBookmarkletVersion_0_1(aConfiguration['formData']); | ||
334 | break; | ||
335 | case '0.2': | ||
336 | fixedConfiguration['formData'] = aConfiguration['formData']; | ||
337 | break; | ||
338 | } | ||
339 | |||
340 | / * | ||
341 | aConfiguration['_inputs'] = []; | ||
342 | c = formData['inputs'].length; | ||
343 | for (i=0; i<c; i++) { | ||
344 | aConfiguration['_inputs'].push(new Clipperz.PM.DataModel.DirectLoginInput(formData['inputs'][i])); | ||
345 | } | ||
346 | * / | ||
347 | / * | ||
348 | aConfiguration['_bindings'] = {}; | ||
349 | if (aConfiguration['legacyBindingData'] == null) { | ||
350 | if (aConfiguration['bindingData'] != null) { | ||
351 | var bindingKey; | ||
352 | |||
353 | for (bindingKey in aConfiguration['bindingData']) { | ||
354 | var newBinding; | ||
355 | |||
356 | newBinding = new Clipperz.PM.DataModel.DirectLoginBinding(bindingKey, {fieldKey:aConfiguration['bindingData'][bindingKey]}); | ||
357 | aConfiguration['_bindings'][newBinding.key()] = newBinding; | ||
358 | } | ||
359 | } else { | ||
360 | var editableFields; | ||
361 | |||
362 | editableFields = MochiKit.Base.filter(function(aField) { | ||
363 | var result; | ||
364 | var type; | ||
365 | |||
366 | type = aField['type'].toLowerCase(); | ||
367 | result = ((type != 'hidden') && (type != 'submit') && (type != 'checkbox') && (type != 'radio') && (type != 'select')); | ||
368 | |||
369 | return result; | ||
370 | }, aConfiguration['_inputs']); | ||
371 | |||
372 | MochiKit.Iter.forEach(editableFields, MochiKit.Base.bind(function(anEditableField) { | ||
373 | var newBinding; | ||
374 | |||
375 | newBinding = new Clipperz.PM.DataModel.DirectLoginBinding(anEditableField['name']); | ||
376 | aConfiguration['_bindings'][newBinding.key()] = newBinding; | ||
377 | }, this)); | ||
378 | } | ||
379 | |||
380 | } else { | ||
381 | var bindingKey; | ||
382 | |||
383 | for (bindingKey in aConfiguration['legacyBindingData']) { | ||
384 | var newBinding; | ||
385 | |||
386 | newBinding = new Clipperz.PM.DataModel.DirectLoginBinding(bindingKey, {fieldName:aConfiguration['legacyBindingData'][bindingKey]}); | ||
387 | aConfiguration['_bindings'][newBinding.key()] = newBinding; | ||
388 | } | ||
389 | } | ||
390 | * / | ||
391 | |||
392 | return fixedConfiguration; | ||
393 | }, | ||
394 | |||
395 | //------------------------------------------------------------------------- | ||
396 | |||
397 | 'getObjectDataStore': function () { | ||
398 | var deferredResult; | ||
399 | |||
400 | deferredResult = new Clipperz.Async.Deferred("DirectLogin.getObjectDataStore", {trace:false}); | ||
401 | deferredResult.acquireLock(this.objectDataStoreDeferredLock()); | ||
402 | deferredResult.addCallback(MochiKit.Base.bind(function () { | ||
403 | var innerDeferredResult; | ||
404 | |||
405 | if (this._objectDataStore == null) { | ||
406 | this._objectDataStore = new Clipperz.KeyValueObjectStore(); | ||
407 | |||
408 | innerDeferredResult = new Clipperz.Async.Deferred("DirectLogin.getObjectDataStore <inner deferred>", {trace:false}); | ||
409 | // innerDeferredResult.addMethod(this.record(), 'getValue', 'directLogins' + '.' + this.reference()); | ||
410 | innerDeferredResult.addMethod(this, 'getValue', ''), | ||
411 | innerDeferredResult.addMethod(this, 'setOriginalState'); | ||
412 | innerDeferredResult.addMethod(this, '_fixConfiguration'); | ||
413 | innerDeferredResult.addMethod(this._objectDataStore, 'initWithValues'); | ||
414 | // innerDeferredResult.addMethod(this._objectDataStore, 'setValues'); | ||
415 | innerDeferredResult.callback(); | ||
416 | } else { | ||
417 | innerDeferredResult = MochiKit.Async.succeed(this._objectDataStore); | ||
418 | } | ||
419 | |||
420 | return innerDeferredResult; | ||
421 | }, this)); | ||
422 | deferredResult.releaseLock(this.objectDataStoreDeferredLock()); | ||
423 | deferredResult.callback(); | ||
424 | |||
425 | return deferredResult; | ||
426 | }, | ||
427 | |||
428 | //------------------------------------------------------------------------- | ||
429 | |||
430 | 'hasInitiatedObjectDataStore': function () { | ||
431 | return (this._objectDataStore != null); | ||
432 | }, | ||
433 | |||
434 | //------------------------------------------------------------------------- | ||
435 | |||
436 | 'resetObjectDataStore': function () { | ||
437 | this._objectDataStore.removeAllData(); | ||
438 | this._objectDataStore = null; | ||
439 | }, | ||
440 | */ | ||
441 | //========================================================================= | ||
442 | |||
443 | 'bookmarkletConfiguration': function () { | ||
444 | return Clipperz.Async.callbacks("DirectLogin.bookmarkletConfiguration", [ | ||
445 | Clipperz.Async.collectResults("DirectLogin.bookmarkletConfiguration <inner results>", { | ||
446 | 'label': MochiKit.Base.method(this, 'label'), | ||
447 | 'configuration': MochiKit.Base.method(this, 'getValue', '') | ||
448 | }, {trace:false}), | ||
449 | function (someValues) { | ||
450 | var result; | ||
451 | |||
452 | if (someValues['configuration'] != null) { | ||
453 | varconfiguration; | ||
454 | |||
455 | configuration = { | ||
456 | 'page': { | ||
457 | 'title': someValues['label'] | ||
458 | //'favicon' | ||
459 | // 'url' | ||
460 | }, | ||
461 | 'form': someValues['configuration']['formData'], | ||
462 | 'version':someValues['configuration']['bookmarkletVersion'] | ||
463 | } | ||
464 | |||
465 | result = Clipperz.Base.formatJSON(configuration); | ||
466 | } else { | ||
467 | result = ''; | ||
468 | } | ||
469 | |||
470 | return result; | ||
471 | } | ||
472 | ], {trace:false}); | ||
473 | |||
474 | }, | ||
475 | |||
476 | //------------------------------------------------------------------------- | ||
477 | |||
478 | 'setBookmarkletConfiguration': function (aValue) { | ||
479 | var bookmarkletConfiguration; | ||
480 | |||
481 | bookmarkletConfiguration = Clipperz.PM.DataModel.DirectLogin.checkBookmarkletConfiguration(aValue); | ||
482 | |||
483 | return Clipperz.Async.callbacks("DirectLogin.setBookmarkletConfiguration", [ | ||
484 | MochiKit.Base.method(this, 'setValue', 'formData', bookmarkletConfiguration['form']), | ||
485 | MochiKit.Base.method(this, 'setValue', 'bookmarkletVersion', bookmarkletConfiguration['version']), | ||
486 | |||
487 | MochiKit.Base.method(this, 'favicon'), | ||
488 | Clipperz.Async.deferredIf("the favicon is not set", [ | ||
489 | ], [ | ||
490 | MochiKit.Base.method(this, 'faviconUrlWithBookmarkletConfiguration', bookmarkletConfiguration), | ||
491 | MochiKit.Base.method(this, 'setFavicon') | ||
492 | ]), | ||
493 | |||
494 | MochiKit.Base.method(this, 'updateInputsAfterChangingBookmarkletConfiguration'), | ||
495 | MochiKit.Base.method(this, 'updateFormValuesAfterChangingBookmarkletConfiguration'), | ||
496 | MochiKit.Base.method(this, 'updateBindingsAfterChangingBookmarkletConfiguration'), | ||
497 | |||
498 | MochiKit.Base.noop | ||
499 | ], {trace:false}); | ||
500 | }, | ||
501 | |||
502 | //========================================================================= | ||
503 | |||
504 | 'formAttributes': function () { | ||
505 | return this.getValue('formData.attributes'); | ||
506 | }, | ||
507 | |||
508 | //========================================================================= | ||
509 | |||
510 | 'inputs': function () { | ||
511 | return Clipperz.Async.callbacks("DirectLogin.inputs", [ | ||
512 | Clipperz.Async.deferredIf("this._inputs is defined", [ | ||
513 | ], [ | ||
514 | MochiKit.Base.method(this, 'updateInputsAfterChangingBookmarkletConfiguration') | ||
515 | ]) | ||
516 | ], {trace:false}, this._inputs); | ||
517 | }, | ||
518 | |||
519 | 'setInputWithFormDataConfiguration': function (aFormDataConfiguration) { | ||
520 | this._inputs = {}; | ||
521 | |||
522 | if (aFormDataConfiguration != null) { | ||
523 | MochiKit.Iter.forEach(aFormDataConfiguration['inputs'], MochiKit.Base.bind(function (anInputData) { | ||
524 | var newInput; | ||
525 | |||
526 | newInput = new Clipperz.PM.DataModel.DirectLoginInput(anInputData); | ||
527 | this._inputs[newInput.name()] = newInput; | ||
528 | }, this)); | ||
529 | } | ||
530 | |||
531 | return this._inputs; | ||
532 | }, | ||
533 | |||
534 | 'updateInputsAfterChangingBookmarkletConfiguration': function () { | ||
535 | return Clipperz.Async.callbacks("DirectLogin.updateInputsAfterChangingBookmarkletConfiguration", [ | ||
536 | MochiKit.Base.method(this, 'getValue', 'formData'), | ||
537 | MochiKit.Base.method(this, 'setInputWithFormDataConfiguration') | ||
538 | ], {trace:false}); | ||
539 | }, | ||
540 | |||
541 | //========================================================================= | ||
542 | |||
543 | 'inputValues': function () { | ||
544 | return Clipperz.Async.callbacks("DirectLogin.inputValues", [ | ||
545 | MochiKit.Base.method(this, 'inputs'), | ||
546 | MochiKit.Base.values, | ||
547 | MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.partial(MochiKit.Base.method(this, 'inputValue'))), | ||
548 | Clipperz.Async.collectAll, | ||
549 | Clipperz.Base.mergeItems | ||
550 | ], {trace:false}); | ||
551 | }, | ||
552 | |||
553 | 'inputValue': function (anInput) { | ||
554 | vardeferredResult; | ||
555 | |||
556 | deferredResult = new Clipperz.Async.Deferred("DirectLogin.inputValue", {trace:false}); | ||
557 | |||
558 | if (anInput.needsFormValue()) { | ||
559 | deferredResult.addMethod(this, 'formValues'); | ||
560 | deferredResult.addCallback(MochiKit.Base.itemgetter(anInput.name())); | ||
561 | deferredResult.addMethodcaller('value'); | ||
562 | } else if (anInput.needsBinding()) { | ||
563 | deferredResult.addMethod(this, 'bindings'); | ||
564 | deferredResult.addCallback(MochiKit.Base.itemgetter(anInput.name())); | ||
565 | deferredResult.addMethodcaller('field'); | ||
566 | deferredResult.addMethodcaller('value'); | ||
567 | } else { | ||
568 | deferredResult.addCallback(MochiKit.Async.succeed, anInput.value()); | ||
569 | } | ||
570 | deferredResult.addCallback(function (anActualValue) { | ||
571 | return [anInput.name(), anActualValue]; | ||
572 | }); | ||
573 | |||
574 | deferredResult.callback(); | ||
575 | |||
576 | return deferredResult; | ||
577 | }, | ||
578 | |||
579 | //========================================================================= | ||
580 | |||
581 | 'bindings': function () { | ||
582 | return Clipperz.Async.callbacks("DirectLogin.bindings", [ | ||
583 | Clipperz.Async.deferredIf("this._bindings is defined", [ | ||
584 | ], [ | ||
585 | MochiKit.Base.method(this, 'updateBindingsAfterChangingBookmarkletConfiguration'), | ||
586 | MochiKit.Base.bind(function () { return this._bindings;}, this) | ||
587 | ]) | ||
588 | ], {trace:false}, this._bindings); | ||
589 | }, | ||
590 | |||
591 | 'bindFormFieldWithLabelToRecordFieldWithLabel': function (aFormFieldLabel, aRecordFieldLabel) { | ||
592 | return Clipperz.Async.callbacks("DirectLogin.bindFormFieldWithLabelToCardFieldWithLabel", [ | ||
593 | Clipperz.Async.collectResults("DirectLogin.bindFormFieldWithLabelToCardFieldWithLabel - collect results", { | ||
594 | 'binding': [ | ||
595 | MochiKit.Base.method(this, 'bindings'), | ||
596 | MochiKit.Base.itemgetter(aFormFieldLabel) | ||
597 | ], | ||
598 | 'field': [ | ||
599 | MochiKit.Base.method(this.record(), 'fieldWithLabel', aRecordFieldLabel) | ||
600 | ] | ||
601 | }), | ||
602 | function (someValues) { | ||
603 | someValues['binding'].setField(someValues['field']) | ||
604 | } | ||
605 | ], {trace:false}); | ||
606 | }, | ||
607 | |||
608 | //------------------------------------------------------------------------- | ||
609 | /* | ||
610 | 'bindingValues': function () { | ||
611 | return Clipperz.Async.callbacks("DirectLogin.bindingValues", [ | ||
612 | Clipperz.Async.collectResults("DirectLogin.bindingValues [collectResults]", { | ||
613 | 'fieldValues': [ | ||
614 | MochiKit.Base.method(this, 'record'), | ||
615 | MochiKit.Base.methodcaller('getFieldsValues') | ||
616 | ], | ||
617 | 'bindings': MochiKit.Base.method(this, 'bindings') | ||
618 | }, {trace:false}), | ||
619 | function (someData) { | ||
620 | var result; | ||
621 | varbindingKey; | ||
622 | |||
623 | result = {}; | ||
624 | for (bindingKey in someData['bindings']) { | ||
625 | result[bindingKey] = someData['fieldValues'][someData['bindings'][bindingKey].fieldKey()]['value']; | ||
626 | } | ||
627 | |||
628 | return result; | ||
629 | } | ||
630 | ], {trace:false}); | ||
631 | }, | ||
632 | */ | ||
633 | //------------------------------------------------------------------------- | ||
634 | |||
635 | 'updateBindingsAfterChangingBookmarkletConfiguration': function () { | ||
636 | return Clipperz.Async.callbacks("DirectLogin.updateBindingsAfterChangingBookmarkletConfiguration", [ | ||
637 | Clipperz.Async.collectResults("DirectLogin.updateBindingsAfterChangingBookmarkletConfiguration<collect results>", { | ||
638 | 'currentValues':MochiKit.Base.method(this, 'getValue', ''), | ||
639 | 'originalValues':MochiKit.Base.method(this, 'originalConfiguration'), | ||
640 | 'inputs': MochiKit.Base.method(this, 'inputs') | ||
641 | }, {trace:false}), | ||
642 | MochiKit.Base.bind(function (someValues) { | ||
643 | var availableBindingValues; | ||
644 | var inputRequiringBindingValues; | ||
645 | var newBindingValues; | ||
646 | |||
647 | if (MochiKit.Base.isUndefinedOrNull(someValues['originalValues']) || MochiKit.Base.isUndefinedOrNull(someValues['originalValues']['bindingData'])) { | ||
648 | availableBindingValues = {}; | ||
649 | } else { | ||
650 | availableBindingValues = Clipperz.Base.deepClone(someValues['originalValues']['bindingData']) | ||
651 | } | ||
652 | |||
653 | if (someValues['currentValues'] != null) { | ||
654 | MochiKit.Base.update(availableBindingValues, someValues['currentValues']['bindingData']); | ||
655 | } | ||
656 | |||
657 | this._bindings = {}; | ||
658 | newBindingValues = {} | ||
659 | MochiKit.Iter.forEach(MochiKit.Base.filter(MochiKit.Base.methodcaller('needsBinding'), MochiKit.Base.values(someValues['inputs'])), MochiKit.Base.bind(function (anInput) { | ||
660 | varnewBinding; | ||
661 | |||
662 | newBindingValues[anInput.name()] = availableBindingValues[anInput.name()]; | ||
663 | newBinding = new Clipperz.PM.DataModel.DirectLoginBinding(this, { | ||
664 | 'key': anInput.name(), | ||
665 | 'field':availableBindingValues[anInput.name()] | ||
666 | }); | ||
667 | |||
668 | this._bindings[anInput.name()] = newBinding; | ||
669 | }, this)) | ||
670 | |||
671 | return newBindingValues; | ||
672 | |||
673 | /* | ||
674 | this._bindings = {}; | ||
675 | |||
676 | if (someValues['currentValues'] != null) { | ||
677 | if (someValues['currentValues']['bindingData'] != null) { | ||
678 | var bindingKey; | ||
679 | |||
680 | for (bindingKey in someValues['currentValues']['bindingData']) { | ||
681 | var newBinding; | ||
682 | |||
683 | newBinding = new Clipperz.PM.DataModel.DirectLoginBinding(this, { | ||
684 | 'key': bindingKey, | ||
685 | 'field':someValues['currentValues']['bindingData'][bindingKey] | ||
686 | }); | ||
687 | this._bindings[newBinding.key()] = newBinding; | ||
688 | } | ||
689 | } else if (someValues['currentValues']['legacyBindingData'] == null) { | ||
690 | var bindingKey; | ||
691 | |||
692 | for (bindingKey in someValues['currentValues']['legacyBindingData']) { | ||
693 | var newBinding; | ||
694 | |||
695 | newBinding = new Clipperz.PM.DataModel.DirectLoginBinding(this, { | ||
696 | 'key': bindingKey, | ||
697 | 'field':someValues['currentValues']['legacyBindingData'][bindingKey] | ||
698 | }); | ||
699 | this._bindings[newBinding.key()] = newBinding; | ||
700 | } | ||
701 | } else { | ||
702 | WTF = TODO; | ||
703 | } | ||
704 | } | ||
705 | |||
706 | return this._bindings; | ||
707 | */ | ||
708 | }, this), | ||
709 | MochiKit.Base.method(this, 'setValue', 'bindingData') | ||
710 | ], {trace:false}); | ||
711 | }, | ||
712 | |||
713 | //========================================================================= | ||
714 | |||
715 | 'formValues': function () { | ||
716 | return Clipperz.Async.callbacks("DirectLogin.formValues", [ | ||
717 | Clipperz.Async.deferredIf("this._formValues is defined", [ | ||
718 | ], [ | ||
719 | MochiKit.Base.method(this, 'updateFormValuesAfterChangingBookmarkletConfiguration'), | ||
720 | MochiKit.Base.bind(function () { return this._formValues;}, this) | ||
721 | ]) | ||
722 | ], {trace:false}, this._formValues); | ||
723 | }, | ||
724 | |||
725 | //------------------------------------------------------------------------- | ||
726 | |||
727 | 'updateFormValuesAfterChangingBookmarkletConfiguration': function () { | ||
728 | return Clipperz.Async.callbacks("DirectLogin.updateFormValuesAfterChangingBookmarkletConfiguration", [ | ||
729 | Clipperz.Async.collectResults("DirectLogin.updateFormValuesAfterChangingBookmarkletConfiguration <collect results>", { | ||
730 | 'currentValues':MochiKit.Base.method(this, 'getValue', ''), | ||
731 | 'originalValues':MochiKit.Base.method(this, 'originalConfiguration'), | ||
732 | 'inputs': MochiKit.Base.method(this, 'inputs') | ||
733 | }, {trace:false}), | ||
734 | MochiKit.Base.bind(function (someValues) { | ||
735 | var availableFormValues; | ||
736 | var inputRequiringFormValues; | ||
737 | var newFormValues; | ||
738 | |||
739 | if (MochiKit.Base.isUndefinedOrNull(someValues['originalValues']) || MochiKit.Base.isUndefinedOrNull(someValues['originalValues']['formValues'])) { | ||
740 | availableFormValues = {}; | ||
741 | } else { | ||
742 | availableFormValues = Clipperz.Base.deepClone(someValues['originalValues']['formValues']) | ||
743 | } | ||
744 | |||
745 | MochiKit.Base.update(availableFormValues, someValues['currentValues']['formValues']); | ||
746 | |||
747 | this._formValues = {}; | ||
748 | newFormValues = {}; | ||
749 | MochiKit.Iter.forEach(MochiKit.Base.filter(MochiKit.Base.methodcaller('needsFormValue'), MochiKit.Base.values(someValues['inputs'])), MochiKit.Base.bind(function (anInput) { | ||
750 | varnewFormValue; | ||
751 | var fieldOptions; | ||
752 | |||
753 | fieldOptions = { | ||
754 | 'type': anInput.type(), | ||
755 | 'options':anInput.options() | ||
756 | }; | ||
757 | |||
758 | newFormValues[anInput.name()] = availableFormValues[anInput.name()] | ||
759 | newFormValue = new Clipperz.PM.DataModel.DirectLoginFormValue(this, { | ||
760 | 'key': anInput.name(), | ||
761 | 'fieldOptions':fieldOptions, | ||
762 | 'value': availableFormValues[anInput.name()] | ||
763 | }); | ||
764 | |||
765 | this._formValues[anInput.name()] = newFormValue; | ||
766 | }, this)) | ||
767 | |||
768 | return newFormValues; | ||
769 | }, this), | ||
770 | MochiKit.Base.method(this, 'setValue', 'formValues') | ||
771 | ], {trace:false}); | ||
772 | }, | ||
773 | |||
774 | //========================================================================= | ||
775 | |||
776 | 'retrieveIndexDataFunction': function () { | ||
777 | return this._retrieveIndexDataFunction; | ||
778 | }, | ||
779 | |||
780 | 'getIndexDataForKey': function (aKey) { | ||
781 | return Clipperz.Async.callbacks("DirectLogin.getIndexDataForKey", [ | ||
782 | MochiKit.Base.partial(this.retrieveIndexDataFunction(), this.reference()), | ||
783 | Clipperz.Async.deferredIf("DirectLogin.getIndexDataForKey - index data not null", [ | ||
784 | MochiKit.Base.itemgetter(aKey) | ||
785 | ],[ | ||
786 | MochiKit.Async.succeed | ||
787 | ]) | ||
788 | ], {trace:false}); | ||
789 | }, | ||
790 | |||
791 | //------------------------------------------------------------------------- | ||
792 | |||
793 | 'setIndexDataForKey': function (aKey, aValue) { | ||
794 | return Clipperz.Async.callbacks("DirectLogin.setValueForKey", [ | ||
795 | MochiKit.Base.method(this, 'getIndexDataForKey', aKey), | ||
796 | MochiKit.Base.bind(function (anActualValue) { | ||
797 | var transientStateKey; | ||
798 | |||
799 | transientStateKey = 'original_' + aKey; | ||
800 | if (MochiKit.Base.isUndefinedOrNull(this.transientState()[transientStateKey])) { | ||
801 | if (anActualValue != aValue) { | ||
802 | this.transientState()[transientStateKey] = anActualValue; | ||
803 | } | ||
804 | } else if (this.transientState()[transientStateKey] == aValue) { | ||
805 | this.transientState()[transientStateKey] = null; | ||
806 | } | ||
807 | }, this), | ||
808 | MochiKit.Base.partial(this._setIndexDataFunction, this.reference(), aKey, aValue) | ||
809 | ], {trace:false}) | ||
810 | }, | ||
811 | |||
812 | //------------------------------------------------------------------------- | ||
813 | /* | ||
814 | 'setValueForKey': function (aKey, aValue) { | ||
815 | return Clipperz.Async.callbacks("DirectLogin.setValueForKey", [ | ||
816 | MochiKit.Base.method(this, 'getIndexDataForKey', aKey), | ||
817 | MochiKit.Base.bind(function (anActualValue) { | ||
818 | var transientStateKey; | ||
819 | |||
820 | transientStateKey = 'original_' + aKey; | ||
821 | if (MochiKit.Base.isUndefinedOrNull(this.transientState()[transientStateKey])) { | ||
822 | if (anActualValue != aValue) { | ||
823 | this.transientState()[transientStateKey] = anActualValue; | ||
824 | } | ||
825 | } else if (this.transientState()[transientStateKey] == aValue) { | ||
826 | this.transientState()[transientStateKey] = null; | ||
827 | } | ||
828 | }, this), | ||
829 | MochiKit.Base.method(this, 'setIndexDataForKey', aKey, aValue) | ||
830 | ], {trace:false}) | ||
831 | }, | ||
832 | */ | ||
833 | //========================================================================= | ||
834 | /* | ||
835 | 'storedConfiguration': function () { | ||
836 | return this.record().getValue('directLogins' + '.' + this.reference()); | ||
837 | }, | ||
838 | |||
839 | //'setStoredConfiguration': function (aValue) { | ||
840 | // return this.record().setValue('directLogins' + '.' + this.reference(), aValue); | ||
841 | //}, | ||
842 | */ | ||
843 | //========================================================================= | ||
844 | |||
845 | 'hasPendingChanges': function () { | ||
846 | varresult; | ||
847 | var deferredResult; | ||
848 | |||
849 | result = false; | ||
850 | result = result || this.isBrandNew(); | ||
851 | result = result || (! MochiKit.Base.isUndefinedOrNull(this.transientState()['original_label'])); | ||
852 | result = result || (! MochiKit.Base.isUndefinedOrNull(this.transientState()['original_favicon'])); | ||
853 | |||
854 | if ((result == false) && (this.originalConfiguration() != null)) { | ||
855 | deferredResult = Clipperz.Async.callbacks("DirectLogin.hasPendingChanges", [ | ||
856 | MochiKit.Base.method(this, 'serializedData'), | ||
857 | MochiKit.Base.bind(function (aCurrentConfiguration) { | ||
858 | varoriginalConfiguration; | ||
859 | var currentConfiguration; | ||
860 | var result; | ||
861 | |||
862 | originalConfiguration = this.originalConfiguration(); | ||
863 | currentConfiguration = aCurrentConfiguration; | ||
864 | |||
865 | result = false; | ||
866 | result = result || (MochiKit.Base.compare(originalConfiguration['bookmarkletVersion'], currentConfiguration['bookmarkletVersion'])!= 0); | ||
867 | result = result || (MochiKit.Base.compare(originalConfiguration['formData'], currentConfiguration['formData']) != 0); | ||
868 | result = result || (MochiKit.Base.compare(originalConfiguration['formValues'], currentConfiguration['formValues']) != 0); | ||
869 | result = result || (MochiKit.Base.compare(originalConfiguration['bindingData'], currentConfiguration['bindingData']) != 0); | ||
870 | |||
871 | return result; | ||
872 | }, this) | ||
873 | ], {trace:false}); | ||
874 | } else { | ||
875 | deferredResult = MochiKit.Async.succeed(result); | ||
876 | } | ||
877 | |||
878 | return deferredResult; | ||
879 | }, | ||
880 | |||
881 | //------------------------------------------------------------------------- | ||
882 | |||
883 | 'revertChanges': function () { | ||
884 | var deferredResult; | ||
885 | |||
886 | if (this.transientState()['original_label'] != null) { | ||
887 | this.setLabel(this.transientState()['original_label']); | ||
888 | } | ||
889 | |||
890 | if (this.transientState()['original_favicon'] != null) { | ||
891 | this.setFavicon(this.transientState()['original_favicon']); | ||
892 | } | ||
893 | |||
894 | if (this.originalConfiguration() != null) { | ||
895 | deferredResult = this.setValue('', this.originalConfiguration()); | ||
896 | } else { | ||
897 | deferredResult = MochiKit.Async.succeed(); | ||
898 | } | ||
899 | |||
900 | this._inputs = null; | ||
901 | this._bindings = null; | ||
902 | this._formValues= null; | ||
903 | |||
904 | this.resetTransientState(false); | ||
905 | |||
906 | /* | ||
907 | if (this.hasInitiatedObjectDataStore()) { | ||
908 | deferredResult = Clipperz.Async.callbacks("DirectLogin.revertChanges", [ | ||
909 | // MochiKit.Base.method(this.record(), 'setValue', 'directLogins' + '.' + this.reference(), this.originalState()), | ||
910 | MochiKit.Base.method(this, 'setValue', '', this.originalState()), | ||
911 | MochiKit.Base.method(this, 'resetObjectDataStore') | ||
912 | ], {trace:false}) | ||
913 | } else { | ||
914 | deferredResult = MochiKit.Async.succeed(); | ||
915 | } | ||
916 | */ | ||
917 | return deferredResult; | ||
918 | }, | ||
919 | |||
920 | |||
921 | //========================================================================= | ||
922 | |||
923 | 'transientState': function () { | ||
924 | if (this._transientState == null) { | ||
925 | this._transientState = {} | ||
926 | } | ||
927 | |||
928 | return this._transientState; | ||
929 | }, | ||
930 | |||
931 | 'resetTransientState': function (isCommitting) { | ||
932 | this._transientState = null; | ||
933 | }, | ||
934 | |||
935 | 'commitTransientState': function (isCommitting) { | ||
936 | this._transientState = null; | ||
937 | this._isBrandNew = false; | ||
938 | }, | ||
939 | |||
940 | //------------------------------------------------------------------------- | ||
941 | |||
942 | 'originalConfiguration': function () { | ||
943 | return this.transientState()['original_configuration']; | ||
944 | }, | ||
945 | |||
946 | 'setOriginalConfiguration': function (aConfiguration) { | ||
947 | this.transientState()['original_configuration'] = Clipperz.Base.deepClone(aConfiguration); | ||
948 | }, | ||
949 | |||
950 | //========================================================================= | ||
951 | |||
952 | 'actualKey': function (aValueKey) { | ||
953 | var actualKey; | ||
954 | |||
955 | actualKey = 'directLogins' + '.' + this.reference(); | ||
956 | if (aValueKey != '') { | ||
957 | actualKey = actualKey + '.' + aValueKey; | ||
958 | } | ||
959 | |||
960 | return actualKey; | ||
961 | }, | ||
962 | |||
963 | //------------------------------------------------------------------------- | ||
964 | |||
965 | 'getValue': function (aValueKey) { | ||
966 | return this.record().getValue(this.actualKey(aValueKey)); | ||
967 | }, | ||
968 | |||
969 | 'setValue': function (aValueKey, aValue) { | ||
970 | // return this.record().setValue(this.actualKey(aValueKey), aValue); | ||
971 | |||
972 | return Clipperz.Async.callbacks("DirectLogin.setValue", [ | ||
973 | MochiKit.Base.method(this, 'getValue', ''), | ||
974 | MochiKit.Base.bind(function (aValue) { | ||
975 | if (this.originalConfiguration() == null) { | ||
976 | this.setOriginalConfiguration(aValue); | ||
977 | } | ||
978 | }, this), | ||
979 | // MochiKit.Base.method(this, 'originalConfiguration'), | ||
980 | // Clipperz.Async.deferredIf("originalConfiguration has been set", [ | ||
981 | // ], [ | ||
982 | // MochiKit.Base.method(this, 'getValue', ''), | ||
983 | // MochiKit.Base.method(this, 'setOriginalConfiguration') | ||
984 | // ]), | ||
985 | MochiKit.Base.method(this.record(), 'setValue', this.actualKey(aValueKey), aValue) | ||
986 | ], {trace:false}); | ||
987 | }, | ||
988 | |||
989 | 'removeValue': function (aValueKey) { | ||
990 | // return this.record().removeValue(this.actualKey(aValueKey)); | ||
991 | |||
992 | return Clipperz.Async.callbacks("DirectLogin.setValue", [ | ||
993 | MochiKit.Base.method(this, 'originalConfiguration'), | ||
994 | Clipperz.Async.deferredIf("originalConfiguration has been set", [ | ||
995 | ], [ | ||
996 | MochiKit.Base.method(this, 'getValue', ''), | ||
997 | MochiKit.Base.method(this, 'setOriginalConfiguration') | ||
998 | ]), | ||
999 | MochiKit.Base.method(this.record(), 'removeValue', this.actualKey(aValueKey)) | ||
1000 | ], {trace:false}); | ||
1001 | }, | ||
1002 | |||
1003 | //========================================================================= | ||
1004 | |||
1005 | 'content': function () { | ||
1006 | // return this.serializedData(); | ||
1007 | // return MochiKit.Async.succeed(this); | ||
1008 | |||
1009 | var deferredResult; | ||
1010 | varfieldValues; | ||
1011 | |||
1012 | fieldValues = {}; | ||
1013 | deferredResult = new Clipperz.Async.Deferred("DirectLogin.content", {trace:false}); | ||
1014 | deferredResult.addMethod(this, 'reference'); | ||
1015 | deferredResult.addCallback(function (aValue) { fieldValues['reference'] = aValue; }); | ||
1016 | deferredResult.addMethod(this, 'label'); | ||
1017 | deferredResult.addCallback(function (aValue) { fieldValues['label'] = aValue; }); | ||
1018 | deferredResult.addMethod(this, 'favicon'); | ||
1019 | deferredResult.addCallback(function (aValue) { fieldValues['favicon'] = aValue; }); | ||
1020 | deferredResult.addCallback(function () { return fieldValues; }); | ||
1021 | deferredResult.callback(); | ||
1022 | |||
1023 | return deferredResult; | ||
1024 | }, | ||
1025 | |||
1026 | //========================================================================= | ||
1027 | |||
1028 | 'deleteAllCleanTextData': function () { | ||
1029 | this._inputs = null; | ||
1030 | this._bindings = null; | ||
1031 | this._formValues = null; | ||
1032 | |||
1033 | this.resetTransientState(); | ||
1034 | }, | ||
1035 | |||
1036 | //------------------------------------------------------------------------- | ||
1037 | |||
1038 | 'hasAnyCleanTextData': function () { | ||
1039 | var result; | ||
1040 | |||
1041 | result = false; | ||
1042 | |||
1043 | result = result || (this._inputs != null); | ||
1044 | result = result || (this._bindings != null); | ||
1045 | result = result || (this._formValues != null); | ||
1046 | result = result || (MochiKit.Base.keys(this.transientState()).length != 0); | ||
1047 | |||
1048 | return MochiKit.Async.succeed(result); | ||
1049 | }, | ||
1050 | |||
1051 | //========================================================================= | ||
1052 | __syntaxFix__: "syntax fix" | ||
1053 | }); | ||
1054 | |||
1055 | //############################################################################# | ||
1056 | |||
1057 | Clipperz.PM.DataModel.DirectLogin.exception = { | ||
1058 | 'WrongBookmarkletConfiguration': new MochiKit.Base.NamedError("Clipperz.PM.DataModel.DirectLogin.exception.WrongBookmarkletConfiguration") | ||
1059 | }; | ||
1060 | |||
1061 | Clipperz.PM.DataModel.DirectLogin.checkBookmarkletConfiguration = function(aConfiguration) { | ||
1062 | var configuration; | ||
1063 | |||
1064 | try { | ||
1065 | configuration = Clipperz.Base.evalJSON(aConfiguration); | ||
1066 | // configuration = Clipperz.PM.BookmarkletProcessor.sanitizeBookmarkletConfiguration(configuration); | ||
1067 | |||
1068 | if (MochiKit.Base.isUndefinedOrNull(configuration['page']['title']) | ||
1069 | ||MochiKit.Base.isUndefinedOrNull(configuration['form']['attributes']['action']) | ||
1070 | // ||MochiKit.Base.isUndefinedOrNull(configuration['form']['attributes']['method']) | ||
1071 | ||MochiKit.Base.isUndefinedOrNull(configuration['form']['inputs']) | ||
1072 | ||MochiKit.Base.isUndefinedOrNull(configuration['version']) | ||
1073 | ) { | ||
1074 | throw Clipperz.PM.DataModel.DirectLogin.exception.WrongBookmarkletConfiguration; | ||
1075 | } | ||
1076 | |||
1077 | // if (MochiKit.Base.isUndefinedOrNull(configuration['favicon'])) { | ||
1078 | // throw Clipperz.PM.DataModel.DirectLogin.exception.WrongBookmarkletConfiguration; | ||
1079 | // } | ||
1080 | |||
1081 | } catch (exception) { | ||
1082 | throw exception; | ||
1083 | } | ||
1084 | |||
1085 | return configuration; | ||
1086 | }; | ||
diff --git a/frontend/delta/js/Clipperz/PM/DataModel/DirectLoginBinding.js b/frontend/delta/js/Clipperz/PM/DataModel/DirectLoginBinding.js new file mode 100644 index 0000000..a8ebb97 --- a/dev/null +++ b/frontend/delta/js/Clipperz/PM/DataModel/DirectLoginBinding.js | |||
@@ -0,0 +1,120 @@ | |||
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.DirectLoginBinding = function(aDirectLogin, args) { | ||
32 | args = args || {}; | ||
33 | |||
34 | this._directLogin = aDirectLogin|| Clipperz.Base.exception.raise('MandatoryParameter'); | ||
35 | |||
36 | this._key = args.key|| Clipperz.Base.exception.raise('MandatoryParameter'); | ||
37 | this._fieldKey = args.field || /* this.directLogin().fieldWithName(args.fieldName).reference() || */null; | ||
38 | |||
39 | return this; | ||
40 | } | ||
41 | |||
42 | Clipperz.PM.DataModel.DirectLoginBinding.prototype = MochiKit.Base.update(null, { | ||
43 | |||
44 | 'toString': function() { | ||
45 | return "DirectLoginBinding (" + this.key() + ", " + this.fieldKey() + ")"; | ||
46 | }, | ||
47 | |||
48 | //------------------------------------------------------------------------- | ||
49 | |||
50 | 'directLogin': function () { | ||
51 | return this._directLogin; | ||
52 | }, | ||
53 | |||
54 | //------------------------------------------------------------------------- | ||
55 | |||
56 | 'key': function() { | ||
57 | return this._key; | ||
58 | }, | ||
59 | |||
60 | //------------------------------------------------------------------------- | ||
61 | |||
62 | 'fieldKey': function() { | ||
63 | return this._fieldKey; | ||
64 | }, | ||
65 | |||
66 | 'setFieldKey': function(aValue) { | ||
67 | this._fieldKey = aValue; | ||
68 | |||
69 | return this.directLogin().setValue('bindingData' + '.' + this.key(), aValue); | ||
70 | }, | ||
71 | |||
72 | //'fieldName': function() { | ||
73 | // return this._fieldName; | ||
74 | //}, | ||
75 | |||
76 | //------------------------------------------------------------------------- | ||
77 | |||
78 | 'field': function() { | ||
79 | var deferredResult; | ||
80 | |||
81 | if (this.fieldKey() != null) { | ||
82 | deferredResult = Clipperz.Async.callbacks("DirectLoginBinding.field [1]", [ | ||
83 | MochiKit.Base.method(this.directLogin().record(), 'fields'), | ||
84 | MochiKit.Base.itemgetter(this.fieldKey()) | ||
85 | ], {trace:false}); | ||
86 | // } else if (this.fieldName() != null) { | ||
87 | // WTF = TODO; | ||
88 | // result = this.directLogin().record().fieldWithName(this.fieldName()); | ||
89 | // | ||
90 | // this.setFieldKey(result.key()); | ||
91 | } else { | ||
92 | deferredResult = MochiKit.Async.succeed(null); | ||
93 | } | ||
94 | |||
95 | return deferredResult; | ||
96 | }, | ||
97 | |||
98 | 'setField': function (aField) { | ||
99 | this.setFieldKey(aField.reference()); | ||
100 | }, | ||
101 | |||
102 | //------------------------------------------------------------------------- | ||
103 | /* | ||
104 | 'fieldValue': function () { | ||
105 | return Clipperz.Async.callbacks("DirectLoginBinding.fieldValue", [ | ||
106 | MochiKit.Base.method('field'), | ||
107 | MochiKit.Base.methodcaller('value') | ||
108 | ], {trace:false}); | ||
109 | }, | ||
110 | */ | ||
111 | //------------------------------------------------------------------------- | ||
112 | |||
113 | 'serializedData': function() { | ||
114 | return this.fieldKey(); | ||
115 | }, | ||
116 | |||
117 | //------------------------------------------------------------------------- | ||
118 | __syntaxFix__: "syntax fix" | ||
119 | }); | ||
120 | |||
diff --git a/frontend/delta/js/Clipperz/PM/DataModel/DirectLoginFormValue.js b/frontend/delta/js/Clipperz/PM/DataModel/DirectLoginFormValue.js new file mode 100644 index 0000000..2429f88 --- a/dev/null +++ b/frontend/delta/js/Clipperz/PM/DataModel/DirectLoginFormValue.js | |||
@@ -0,0 +1,101 @@ | |||
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.DirectLoginFormValue = function(aDirectLogin, args) { | ||
32 | args = args || {}; | ||
33 | |||
34 | this._directLogin = aDirectLogin|| Clipperz.Base.exception.raise('MandatoryParameter'); | ||
35 | |||
36 | this._key = args.key || Clipperz.Base.exception.raise('MandatoryParameter'); | ||
37 | this._fieldOptions = args.fieldOptions|| Clipperz.Base.exception.raise('MandatoryParameter'); | ||
38 | this._value = args.value || null; | ||
39 | |||
40 | return this; | ||
41 | } | ||
42 | |||
43 | Clipperz.PM.DataModel.DirectLoginFormValue.prototype = MochiKit.Base.update(null, { | ||
44 | |||
45 | 'toString': function() { | ||
46 | return "DirectLoginFormValue (" + this.key() + ", " + this.value() + ")"; | ||
47 | }, | ||
48 | |||
49 | //------------------------------------------------------------------------- | ||
50 | |||
51 | 'directLogin': function () { | ||
52 | return this._directLogin; | ||
53 | }, | ||
54 | |||
55 | //------------------------------------------------------------------------- | ||
56 | |||
57 | 'key': function() { | ||
58 | return this._key; | ||
59 | }, | ||
60 | |||
61 | //------------------------------------------------------------------------- | ||
62 | |||
63 | 'fieldOptions': function() { | ||
64 | return this._fieldOptions; | ||
65 | }, | ||
66 | |||
67 | //------------------------------------------------------------------------- | ||
68 | |||
69 | 'type': function () { | ||
70 | return this.fieldOptions()['type']; | ||
71 | }, | ||
72 | |||
73 | //------------------------------------------------------------------------- | ||
74 | |||
75 | 'value': function() { | ||
76 | varresult; | ||
77 | |||
78 | result = this._value; | ||
79 | |||
80 | // if ((result == null) && (this.type() == 'checkbox')) { | ||
81 | // result = false; | ||
82 | // }; | ||
83 | |||
84 | return result; | ||
85 | }, | ||
86 | |||
87 | 'setValue': function (aValue) { | ||
88 | this._value = aValue; | ||
89 | return this.directLogin().setValue('formValues' + '.' + this.key(), aValue); | ||
90 | }, | ||
91 | |||
92 | //------------------------------------------------------------------------- | ||
93 | /* | ||
94 | 'serializedData': function() { | ||
95 | return this.value(); | ||
96 | }, | ||
97 | */ | ||
98 | //------------------------------------------------------------------------- | ||
99 | __syntaxFix__: "syntax fix" | ||
100 | }); | ||
101 | |||
diff --git a/frontend/delta/js/Clipperz/PM/DataModel/DirectLoginInput.js b/frontend/delta/js/Clipperz/PM/DataModel/DirectLoginInput.js new file mode 100644 index 0000000..d9995fc --- a/dev/null +++ b/frontend/delta/js/Clipperz/PM/DataModel/DirectLoginInput.js | |||
@@ -0,0 +1,192 @@ | |||
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 | Clipperz.PM.DataModel.DirectLoginInput = function(args) { | ||
31 | this._args = args; | ||
32 | |||
33 | return this; | ||
34 | } | ||
35 | |||
36 | Clipperz.PM.DataModel.DirectLoginInput.prototype = MochiKit.Base.update(null, { | ||
37 | |||
38 | 'args': function() { | ||
39 | return this._args; | ||
40 | }, | ||
41 | |||
42 | //------------------------------------------------------------------------- | ||
43 | |||
44 | 'name': function() { | ||
45 | return this.args()['name']; | ||
46 | }, | ||
47 | |||
48 | //------------------------------------------------------------------------- | ||
49 | |||
50 | 'type': function() { | ||
51 | var result; | ||
52 | |||
53 | result = this.args()['type']; | ||
54 | |||
55 | if (result != null) { | ||
56 | result = result.toLowerCase(); | ||
57 | } | ||
58 | return result; | ||
59 | }, | ||
60 | |||
61 | //------------------------------------------------------------------------- | ||
62 | |||
63 | 'options': function() { | ||
64 | return this.args()['options']; | ||
65 | }, | ||
66 | |||
67 | //------------------------------------------------------------------------- | ||
68 | |||
69 | 'value': function() { | ||
70 | return this.args()['value']; | ||
71 | }, | ||
72 | |||
73 | //------------------------------------------------------------------------- | ||
74 | /* | ||
75 | 'formConfiguration': function(someFormValues, someBindings, someFields) { | ||
76 | var result; | ||
77 | |||
78 | if (this.shouldSetValue()) { | ||
79 | switch (this.type()) { | ||
80 | case 'select': | ||
81 | var currentValue; | ||
82 | var options; | ||
83 | |||
84 | // currentValue = this.directLogin()._configuration['formValues'][this.name()]; | ||
85 | currentValue = someFormValues[this.name()]; | ||
86 | options = this.args()['options']; | ||
87 | |||
88 | result = MochiKit.DOM.SELECT({name:this.name()}, | ||
89 | MochiKit.Base.map(function(anOption) { | ||
90 | var options; | ||
91 | |||
92 | options = {value:anOption['value']}; | ||
93 | if (currentValue == anOption['value']) { | ||
94 | options.selected = true; | ||
95 | } | ||
96 | |||
97 | return MochiKit.DOM.OPTION(options, anOption['label']) | ||
98 | }, options) | ||
99 | ) | ||
100 | break; | ||
101 | case 'checkbox': | ||
102 | var options; | ||
103 | |||
104 | options = {type:'checkbox', name: this.name()}; | ||
105 | // if (this.directLogin()._configuration['formValues'][this.name()] == true) { | ||
106 | if (someFormValues[this.name()] == true) { | ||
107 | options['checked'] = true; | ||
108 | }; | ||
109 | |||
110 | result = MochiKit.DOM.INPUT(options, null); | ||
111 | break; | ||
112 | case 'radio': | ||
113 | var currentName; | ||
114 | var currentValue; | ||
115 | var options; | ||
116 | |||
117 | currentName = this.name(); | ||
118 | // currentValue = this.directLogin()._configuration['formValues'][this.name()]; | ||
119 | currentValue = someFormValues[this.name()]; | ||
120 | options = this.args()['options']; | ||
121 | |||
122 | result = MochiKit.DOM.DIV(null, | ||
123 | MochiKit.Base.map(function(anOption) { | ||
124 | var options; | ||
125 | var isChecked; | ||
126 | var inputNode; | ||
127 | var divNode; | ||
128 | |||
129 | options = {type:'radio', name:currentName, value:anOption['value']} | ||
130 | isChecked = (currentValue == anOption['value']); | ||
131 | if (isChecked) { | ||
132 | options.checked = true; | ||
133 | } | ||
134 | |||
135 | if (Clipperz_IEisBroken == true) { | ||
136 | var checkedValue; | ||
137 | |||
138 | checkedValue = (isChecked ? " CHECKED" : ""); | ||
139 | inputNode = MochiKit.DOM.currentDocument().createElement("<INPUT TYPE='RADIO' NAME='" + currentName + "' VALUE='" + anOption['value'] + "'" + checkedValue + ">"); | ||
140 | } else { | ||
141 | inputNode = MochiKit.DOM.INPUT(options, anOption['value']); | ||
142 | } | ||
143 | divNode = MochiKit.DOM.DIV(null, inputNode); | ||
144 | |||
145 | return divNode; | ||
146 | }, options) | ||
147 | ); | ||
148 | break; | ||
149 | } | ||
150 | } else { | ||
151 | var binding; | ||
152 | // binding = this.directLogin().bindings()[this.name()]; | ||
153 | binding = someBindings[this.name()]; | ||
154 | |||
155 | result = MochiKit.DOM.INPUT({ | ||
156 | type:((this.type() != 'password') ? this.type() : 'text'), | ||
157 | name:this.name(), | ||
158 | // value:((binding != null)? binding.field().value() : this.value()) | ||
159 | value:((binding != null)? someFields[binding.fieldKey()]['value'] : this.value()) | ||
160 | // value:((binding != null)? someFields[binding.fieldKey()].value() : this.value()) | ||
161 | }, null); | ||
162 | } | ||
163 | |||
164 | return result; | ||
165 | }, | ||
166 | */ | ||
167 | //------------------------------------------------------------------------- | ||
168 | |||
169 | 'needsFormValue': function() { | ||
170 | var type; | ||
171 | var result; | ||
172 | |||
173 | type = this.type(); | ||
174 | result = ((type == 'checkbox') || (type == 'radio') || (type == 'select')); | ||
175 | |||
176 | return result; | ||
177 | }, | ||
178 | |||
179 | 'needsBinding': function() { | ||
180 | var type; | ||
181 | var result; | ||
182 | |||
183 | type = this.type(); | ||
184 | result = ((type == 'text') || (type == 'password')); | ||
185 | |||
186 | return result; | ||
187 | }, | ||
188 | |||
189 | //------------------------------------------------------------------------- | ||
190 | __syntaxFix__: "syntax fix" | ||
191 | }); | ||
192 | |||
diff --git a/frontend/delta/js/Clipperz/PM/DataModel/EncryptedRemoteObject.js b/frontend/delta/js/Clipperz/PM/DataModel/EncryptedRemoteObject.js new file mode 100644 index 0000000..1aa7a52 --- a/dev/null +++ b/frontend/delta/js/Clipperz/PM/DataModel/EncryptedRemoteObject.js | |||
@@ -0,0 +1,542 @@ | |||
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 | try { if (typeof(Clipperz.KeyValueObjectStore) == 'undefined') { throw ""; }} catch (e) { | ||
25 | throw "Clipperz.PM.DataModel.EncryptedRemoteObject depends on Clipperz.KeyValueObjectStore!"; | ||
26 | } | ||
27 | |||
28 | if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; } | ||
29 | if (typeof(Clipperz.PM.DataModel) == 'undefined') { Clipperz.PM.DataModel = {}; } | ||
30 | |||
31 | Clipperz.PM.DataModel.EncryptedRemoteObject = function(args) { | ||
32 | args = args || {}; | ||
33 | |||
34 | this._name = args.name || null; | ||
35 | this._reference = args.reference || Clipperz.PM.Crypto.randomKey(); | ||
36 | this._isBrandNew = ((args.reference == null) && (args.remoteData == null)); | ||
37 | |||
38 | if ((this._isBrandNew == false) && (args['retrieveKeyFunction'] == null)) { | ||
39 | Clipperz.Base.exception.raise('MandatoryParameter'); | ||
40 | } else { | ||
41 | this._retrieveKeyFunction = args['retrieveKeyFunction']; | ||
42 | } | ||
43 | |||
44 | this._retrieveRemoteDataFunction = args.retrieveRemoteDataFunction|| null; | ||
45 | this._remoteData = args.remoteData || null; | ||
46 | // this._remoteData = args.remoteData ? Clipperz.Base.deepClone(args.remoteData) : null; | ||
47 | if ((!this._isBrandNew) && ((this._retrieveRemoteDataFunction == null) && (this._remoteData == null))) { | ||
48 | Clipperz.Base.exception.raise('MandatoryParameter'); | ||
49 | } | ||
50 | |||
51 | |||
52 | this._encryptedDataKeypath = args.encryptedDataKeypath || 'data'; //Clipperz.Base.exception.raise('MandatoryParameter'); | ||
53 | this._encryptedVersionKeypath = args.encryptedVersionKeypath || 'version';//Clipperz.Base.exception.raise('MandatoryParameter'); | ||
54 | |||
55 | |||
56 | this._transientState = null; | ||
57 | this._deferredLocks = {}; | ||
58 | |||
59 | if (this._isBrandNew == true) { | ||
60 | this._objectDataStore = new Clipperz.KeyValueObjectStore(/*{'name':'EncryptedRemoteObject.objectDataStore [1]'}*/); | ||
61 | } else { | ||
62 | this._objectDataStore = null; | ||
63 | } | ||
64 | |||
65 | return this; | ||
66 | } | ||
67 | |||
68 | // | ||
69 | // Basic data workflow | ||
70 | //======================= | ||
71 | // | ||
72 | //getRemoteData | ||
73 | // unpackRemoteData | ||
74 | // getDecryptData [encryptedDataKeypath, encryptedVersionKeypath] | ||
75 | // unpackData | ||
76 | // | ||
77 | // | ||
78 | // ?? packData | ||
79 | // ?? encryptDataWithKey | ||
80 | // ??packRemoteData [encryptedDataKeypath (?), encryptedVersionKeypath (?)] | ||
81 | // | ||
82 | |||
83 | Clipperz.PM.DataModel.EncryptedRemoteObject.prototype = MochiKit.Base.update(null, { | ||
84 | |||
85 | 'toString': function () { | ||
86 | return "Clipperz.PM.DataModel.EncryptedRemoteObject" + (this.name() != null ? " - " + this.name() : ""); | ||
87 | }, | ||
88 | |||
89 | //------------------------------------------------------------------------- | ||
90 | |||
91 | 'name': function () { | ||
92 | return this._name; | ||
93 | }, | ||
94 | |||
95 | //------------------------------------------------------------------------- | ||
96 | |||
97 | 'reference': function () { | ||
98 | return this._reference; | ||
99 | }, | ||
100 | |||
101 | 'setReference': function (aValue) { | ||
102 | this._reference = aValue; | ||
103 | |||
104 | return this._reference; | ||
105 | }, | ||
106 | |||
107 | //------------------------------------------------------------------------- | ||
108 | |||
109 | 'transientState': function () { | ||
110 | if (this._transientState == null) { | ||
111 | this._transientState = new Clipperz.KeyValueObjectStore(/*{'name':'EncryptedRemoteObject.transientState [2]'}*/); | ||
112 | } | ||
113 | |||
114 | return this._transientState; | ||
115 | }, | ||
116 | |||
117 | 'resetTransientState': function (isCommitting) { | ||
118 | if (this._transientState != null) { | ||
119 | this._transientState.removeAllData(); | ||
120 | } | ||
121 | |||
122 | this._transientState = null; | ||
123 | }, | ||
124 | |||
125 | //------------------------------------------------------------------------- | ||
126 | |||
127 | 'isBrandNew': function () { | ||
128 | return this._isBrandNew; | ||
129 | }, | ||
130 | |||
131 | //------------------------------------------------------------------------- | ||
132 | |||
133 | 'getKey': function () { | ||
134 | var deferredResult; | ||
135 | var deferredLock; | ||
136 | |||
137 | deferredLock = this.getDeferredLockForKey('key'); | ||
138 | |||
139 | deferredResult = new Clipperz.Async.Deferred("EncryptedRemoteObject.getKey", {trace:false}); | ||
140 | deferredResult.acquireLock(deferredLock); | ||
141 | deferredResult.addMethod( | ||
142 | this.decryptedDataStore(), | ||
143 | 'deferredGetOrSet', | ||
144 | 'decryptionKey', | ||
145 | MochiKit.Base.partial(this.retrieveKeyFunction(), this.reference()) | ||
146 | ); | ||
147 | deferredResult.releaseLock(deferredLock); | ||
148 | deferredResult.callback(); | ||
149 | |||
150 | return deferredResult; | ||
151 | }, | ||
152 | |||
153 | // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . | ||
154 | |||
155 | 'retrieveKeyFunction': function () { | ||
156 | return this._retrieveKeyFunction; | ||
157 | }, | ||
158 | |||
159 | 'setRetrieveKeyFunction': function (aFunction) { | ||
160 | this._retrieveKeyFunction = aFunction; | ||
161 | }, | ||
162 | |||
163 | //------------------------------------------------------------------------- | ||
164 | |||
165 | 'hasLoadedRemoteData': function () { | ||
166 | return (this._remoteData != null); | ||
167 | }, | ||
168 | |||
169 | 'getRemoteData': function () { | ||
170 | var deferredResult; | ||
171 | vardeferredLock; | ||
172 | |||
173 | deferredLock = this.getDeferredLockForKey('remoteData'); | ||
174 | |||
175 | deferredResult = new Clipperz.Async.Deferred("EncryptedRemoteObjects.getRemoteData", {trace:false}); | ||
176 | deferredResult.acquireLock(deferredLock); | ||
177 | deferredResult.addCallback(MochiKit.Base.bind(function () { | ||
178 | var innerDeferredResult; | ||
179 | |||
180 | if (this._remoteData != null) { | ||
181 | innerDeferredResult = MochiKit.Async.succeed(this._remoteData); | ||
182 | } else { | ||
183 | innerDeferredResult = Clipperz.Async.callbacks("EncryptedRemoteObjects.getRemoteData <inner deferred>", [ | ||
184 | MochiKit.Base.partial(this.retrieveRemoteDataFunction(), this.reference()), | ||
185 | MochiKit.Base.method(this, 'unpackRemoteData'), | ||
186 | MochiKit.Base.bind(function (someData) { | ||
187 | this._remoteData = someData; | ||
188 | return this._remoteData; | ||
189 | }, this) | ||
190 | ], {trace:false}); | ||
191 | } | ||
192 | |||
193 | return innerDeferredResult; | ||
194 | }, this)) | ||
195 | deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress'); | ||
196 | deferredResult.releaseLock(deferredLock); | ||
197 | |||
198 | deferredResult.callback(); | ||
199 | |||
200 | return deferredResult; | ||
201 | }, | ||
202 | |||
203 | //------------------------------------------------------------------------- | ||
204 | |||
205 | 'unpackRemoteData': function (someData) { | ||
206 | return MochiKit.Async.succeed(someData); | ||
207 | }, | ||
208 | |||
209 | //......................................................................... | ||
210 | |||
211 | 'packRemoteData': function (someData) { | ||
212 | var result; | ||
213 | |||
214 | result = { | ||
215 | 'reference':this.reference(), | ||
216 | 'data': someData, | ||
217 | 'version': Clipperz.PM.Crypto.encryptingFunctions.currentVersion | ||
218 | }; | ||
219 | |||
220 | return MochiKit.Async.succeed(result); | ||
221 | }, | ||
222 | |||
223 | //------------------------------------------------------------------------- | ||
224 | |||
225 | 'retrieveRemoteDataFunction': function () { | ||
226 | return this._retrieveRemoteDataFunction; | ||
227 | }, | ||
228 | |||
229 | 'setRetrieveRemoteDataFunction': function (aFunction) { | ||
230 | this._retrieveRemoteDataFunction = aFunction; | ||
231 | }, | ||
232 | |||
233 | //------------------------------------------------------------------------- | ||
234 | |||
235 | 'decryptedDataStore': function () { | ||
236 | if (this._decryptedDataStore == null) { | ||
237 | this._decryptedDataStore = new Clipperz.KeyValueObjectStore(/*{'name':'EncryptedRemoteObject.decryptedDataStore [3]'}*/); | ||
238 | }; | ||
239 | |||
240 | return this._decryptedDataStore; | ||
241 | }, | ||
242 | |||
243 | //......................................................................... | ||
244 | |||
245 | 'getDecryptedData': function () { | ||
246 | var deferredResult; | ||
247 | var deferredLock; | ||
248 | |||
249 | deferredLock = this.getDeferredLockForKey('decryptedData'); | ||
250 | |||
251 | deferredResult = new Clipperz.Async.Deferred("EncryptedRemoteObject.getDecryptedData", {trace:false}); | ||
252 | deferredResult.acquireLock(deferredLock); | ||
253 | deferredResult.addMethod(this, 'decryptedDataStore'); | ||
254 | deferredResult.addCallback(MochiKit.Base.methodcaller('deferredGetOrSet', 'decryptedData', MochiKit.Base.bind(function () { | ||
255 | varinnerDeferredResult; | ||
256 | |||
257 | innerDeferredResult = new Clipperz.Async.Deferred("EncryptedRemoteObject.getDecryptedData <inner deferred>", {trace:false}); | ||
258 | |||
259 | innerDeferredResult.addMethod(this, 'getRemoteData'); | ||
260 | innerDeferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress'); | ||
261 | innerDeferredResult.collectResults({ | ||
262 | 'key': MochiKit.Base.method(this, 'getKey'), | ||
263 | 'value':MochiKit.Base.itemgetter(this._encryptedDataKeypath), | ||
264 | 'version':MochiKit.Base.itemgetter(this._encryptedVersionKeypath) | ||
265 | }); | ||
266 | |||
267 | innerDeferredResult.addCallback(Clipperz.PM.Crypto.deferredDecrypt); | ||
268 | innerDeferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress'); | ||
269 | innerDeferredResult.addMethod(this, 'unpackData'); | ||
270 | innerDeferredResult.callback(); | ||
271 | |||
272 | return innerDeferredResult; | ||
273 | }, this))); | ||
274 | deferredResult.releaseLock(deferredLock); | ||
275 | deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress'); | ||
276 | deferredResult.callback(); | ||
277 | |||
278 | return deferredResult; | ||
279 | }, | ||
280 | |||
281 | //------------------------------------------------------------------------- | ||
282 | |||
283 | 'setValue': function(aKey, aValue) { | ||
284 | var deferredResult; | ||
285 | |||
286 | deferredResult = new Clipperz.Async.Deferred("EncryptedRemoteObject.setValue", {trace:false}); | ||
287 | deferredResult.addMethod(this, '_getObjectDataStore'); | ||
288 | deferredResult.addCallback(MochiKit.Base.methodcaller('setValue', aKey, aValue)); | ||
289 | deferredResult.callback(); | ||
290 | |||
291 | return deferredResult; | ||
292 | }, | ||
293 | |||
294 | //......................................................................... | ||
295 | |||
296 | 'getValue': function (aKey) { | ||
297 | return Clipperz.Async.callbacks("EncryptedRemoteObject.getValue", [ | ||
298 | MochiKit.Base.method(this, '_getObjectDataStore'), | ||
299 | MochiKit.Base.methodcaller('getValue', aKey) | ||
300 | ], {trace:false}); | ||
301 | }, | ||
302 | |||
303 | //......................................................................... | ||
304 | |||
305 | 'removeValue': function (aKey) { | ||
306 | return Clipperz.Async.callbacks("EncryptedRemoteObject.removeValue", [ | ||
307 | MochiKit.Base.method(this, '_getObjectDataStore'), | ||
308 | MochiKit.Base.methodcaller('removeValue', aKey) | ||
309 | ], {trace:false}); | ||
310 | }, | ||
311 | |||
312 | //......................................................................... | ||
313 | |||
314 | 'values': function () { | ||
315 | return Clipperz.Async.callbacks("EncryptedRemoteObject.values", [ | ||
316 | MochiKit.Base.method(this, '_getObjectDataStore'), | ||
317 | MochiKit.Base.methodcaller('values') | ||
318 | ], {trace:false}); | ||
319 | }, | ||
320 | |||
321 | 'setValues': function (someValues) { | ||
322 | return Clipperz.Async.callbacks("EncryptedRemoteObject.values", [ | ||
323 | MochiKit.Base.method(this, '_getObjectDataStore'), | ||
324 | MochiKit.Base.methodcaller('setValues', someValues) | ||
325 | ], {trace:false}); | ||
326 | }, | ||
327 | |||
328 | //......................................................................... | ||
329 | |||
330 | '_getObjectDataStore': function () { | ||
331 | var deferredResult; | ||
332 | var deferredLock; | ||
333 | |||
334 | deferredLock = this.getDeferredLockForKey('objectDataStore'); | ||
335 | |||
336 | deferredResult = new Clipperz.Async.Deferred("EncryptedRemoteObject._getObjectDataStore", {trace:false}); | ||
337 | deferredResult.acquireLock(deferredLock); | ||
338 | deferredResult.addCallback(MochiKit.Base.bind(function () { | ||
339 | var innerDeferredResult; | ||
340 | |||
341 | if (this._objectDataStore == null) { | ||
342 | this._objectDataStore = new Clipperz.KeyValueObjectStore(/*{'name':'EncryptedRemoteObject.objectDataStore [4]'}*/); | ||
343 | |||
344 | innerDeferredResult = new Clipperz.Async.Deferred("EncryptedRemoteObject._getObjectDataStore <inner deferred>", {trace:false}); | ||
345 | innerDeferredResult.addMethod(this, 'getDecryptedData'); | ||
346 | innerDeferredResult.addMethod(this._objectDataStore, 'initWithValues'); | ||
347 | innerDeferredResult.callback(); | ||
348 | } else { | ||
349 | innerDeferredResult = MochiKit.Async.succeed(this._objectDataStore); | ||
350 | } | ||
351 | |||
352 | return innerDeferredResult; | ||
353 | }, this)); | ||
354 | deferredResult.releaseLock(deferredLock); | ||
355 | deferredResult.callback(); | ||
356 | |||
357 | return deferredResult; | ||
358 | }, | ||
359 | |||
360 | 'hasInitiatedObjectDataStore': function () { | ||
361 | return (this._objectDataStore != null); | ||
362 | }, | ||
363 | |||
364 | //------------------------------------------------------------------------- | ||
365 | |||
366 | 'getDeferredLockForKey': function (aKey) { | ||
367 | var result; | ||
368 | |||
369 | result = this._deferredLocks[aKey]; | ||
370 | |||
371 | if (typeof(result) == 'undefined') { | ||
372 | result = new MochiKit.Async.DeferredLock(); | ||
373 | this._deferredLocks[aKey] = result; | ||
374 | } | ||
375 | |||
376 | return result; | ||
377 | }, | ||
378 | |||
379 | //------------------------------------------------------------------------- | ||
380 | |||
381 | 'unpackData': function (someData) { //++ | ||
382 | return someData; | ||
383 | }, | ||
384 | |||
385 | 'packData': function (someData) { //++ | ||
386 | return someData; | ||
387 | }, | ||
388 | |||
389 | //------------------------------------------------------------------------- | ||
390 | |||
391 | 'hasPendingChanges': function () { | ||
392 | var deferredResult; | ||
393 | var tempObj = this; | ||
394 | |||
395 | if (this.isBrandNew()) { | ||
396 | // deferredResult = MochiKit.Async.succeed(true); | ||
397 | deferredResult = this.hasPendingChangesWhenBrandNew(); | ||
398 | } else if (this.hasInitiatedObjectDataStore()) { | ||
399 | deferredResult = new Clipperz.Async.Deferred("EncryptedRemoteObject.hasPendingChanges", {trace:false}); | ||
400 | deferredResult.collectResults({ | ||
401 | 'decryptedData': [ | ||
402 | MochiKit.Base.method(this, 'getDecryptedData'), | ||
403 | Clipperz.Base.serializeJSON | ||
404 | ], | ||
405 | 'objectData': [ | ||
406 | MochiKit.Base.method(this, '_getObjectDataStore'), | ||
407 | MochiKit.Base.methodcaller('values'), | ||
408 | Clipperz.Base.serializeJSON | ||
409 | ] | ||
410 | }); | ||
411 | deferredResult.addCallback(function (someValues) { | ||
412 | return (someValues['decryptedData'] != someValues['objectData']); | ||
413 | }); | ||
414 | deferredResult.callback(); | ||
415 | } else { | ||
416 | deferredResult = MochiKit.Async.succeed(false); | ||
417 | } | ||
418 | |||
419 | return deferredResult; | ||
420 | }, | ||
421 | |||
422 | 'hasPendingChangesWhenBrandNew': function () { | ||
423 | return MochiKit.Async.succeed(true); | ||
424 | }, | ||
425 | |||
426 | //------------------------------------------------------------------------- | ||
427 | |||
428 | 'commitTransientState': function () { | ||
429 | var deferredResult; | ||
430 | |||
431 | // if (this.transientState().getValue('__prepareRemoteData') == true) { | ||
432 | if (this.transientState().getValue('packedRemoteData') != null) { | ||
433 | deferredResult = Clipperz.Async.callbacks("EncryptedRemoteObject.commitTransientState - prepareRemoteData", [ | ||
434 | MochiKit.Base.bind(function (someData) { | ||
435 | this._remoteData = this.transientState().getValue('packedRemoteData'); | ||
436 | }, this), | ||
437 | |||
438 | MochiKit.Base.method(this, '_getObjectDataStore'), | ||
439 | MochiKit.Base.methodcaller('values'), | ||
440 | Clipperz.Base.deepClone, | ||
441 | MochiKit.Base.method(this.decryptedDataStore(), 'setValue', 'decryptedData'), | ||
442 | |||
443 | MochiKit.Base.method(this, 'resetTransientState', true) | ||
444 | ], {trace:false}); | ||
445 | |||
446 | } else { | ||
447 | deferredResult = Clipperz.Async.callbacks("EncryptedRemoteObject.commitTransientState - NO prepareRemoteData", [ | ||
448 | MochiKit.Base.method(this, 'resetTransientState', true) | ||
449 | ], {trace:false}); | ||
450 | } | ||
451 | |||
452 | this._isBrandNew = false; | ||
453 | |||
454 | return deferredResult; | ||
455 | }, | ||
456 | |||
457 | //------------------------------------------------------------------------- | ||
458 | |||
459 | 'revertChanges': function () { | ||
460 | if (this.hasInitiatedObjectDataStore()) { | ||
461 | this._objectDataStore.removeAllData(); | ||
462 | this._objectDataStore = null; | ||
463 | } | ||
464 | this.resetTransientState(false); | ||
465 | |||
466 | return MochiKit.Async.succeed(); | ||
467 | }, | ||
468 | |||
469 | //------------------------------------------------------------------------- | ||
470 | |||
471 | 'deleteAllCleanTextData': function () { | ||
472 | var deferredResult; | ||
473 | |||
474 | deferredResult = new Clipperz.Async.Deferred("EncryptedRemoteObject.deleteAllCleanTextData", {trace:false}); | ||
475 | |||
476 | deferredResult.addMethod(this, 'resetTransientState', false); | ||
477 | |||
478 | deferredResult.acquireLock(this.getDeferredLockForKey('decryptedData')); | ||
479 | deferredResult.addCallback(MochiKit.Base.bind(function () { | ||
480 | if (this._decryptedDataStore != null) { | ||
481 | this._decryptedDataStore.removeAllData(); | ||
482 | } | ||
483 | }, this)); | ||
484 | deferredResult.releaseLock(this.getDeferredLockForKey('decryptedData')); | ||
485 | |||
486 | deferredResult.acquireLock(this.getDeferredLockForKey('objectDataStore')); | ||
487 | deferredResult.addCallback(MochiKit.Base.bind(function () { | ||
488 | if (this._objectDataStore != null) { | ||
489 | this._objectDataStore.removeAllData(); | ||
490 | this._objectDataStore = null; | ||
491 | } | ||
492 | }, this)); | ||
493 | deferredResult.releaseLock(this.getDeferredLockForKey('objectDataStore')); | ||
494 | |||
495 | deferredResult.callback(); | ||
496 | |||
497 | return deferredResult; | ||
498 | }, | ||
499 | |||
500 | //......................................................................... | ||
501 | |||
502 | 'hasAnyCleanTextData': function () { | ||
503 | var result; | ||
504 | |||
505 | result = false; | ||
506 | |||
507 | result = result || (! this.decryptedDataStore().isEmpty()); | ||
508 | result = result || (! this.transientState().isEmpty()); | ||
509 | if (this.hasInitiatedObjectDataStore()) { | ||
510 | result = result || (! this._objectDataStore.isEmpty()); | ||
511 | } | ||
512 | |||
513 | return MochiKit.Async.succeed(result); | ||
514 | }, | ||
515 | |||
516 | //------------------------------------------------------------------------- | ||
517 | |||
518 | 'prepareRemoteDataWithKey': function (aKey) { | ||
519 | return Clipperz.Async.callbacks("EncryptedRemoteObject.prepareRemoteDataWithKey", [ | ||
520 | // MochiKit.Base.method(this.transientState(), 'setValue', '__prepareRemoteData', true), | ||
521 | MochiKit.Base.method(this, '_getObjectDataStore'), | ||
522 | MochiKit.Base.methodcaller('values'), | ||
523 | MochiKit.Base.method(this, 'packData'), | ||
524 | function (someData) { | ||
525 | return Clipperz.PM.Crypto.deferredEncrypt({ | ||
526 | 'key': aKey, | ||
527 | 'value':someData, | ||
528 | 'version':Clipperz.PM.Crypto.encryptingFunctions.currentVersion | ||
529 | }) | ||
530 | }, | ||
531 | MochiKit.Base.method(this, 'packRemoteData'), | ||
532 | MochiKit.Base.method(this.transientState(), 'setValue', 'packedRemoteData'), | ||
533 | function (someData) { | ||
534 | MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'advanceProgress'); | ||
535 | return someData; | ||
536 | } | ||
537 | ], {trace:false}); | ||
538 | }, | ||
539 | |||
540 | //------------------------------------------------------------------------- | ||
541 | __syntaxFix__: "syntax fix" | ||
542 | }); | ||
diff --git a/frontend/delta/js/Clipperz/PM/DataModel/OneTimePassword.js b/frontend/delta/js/Clipperz/PM/DataModel/OneTimePassword.js new file mode 100644 index 0000000..fbca1ff --- a/dev/null +++ b/frontend/delta/js/Clipperz/PM/DataModel/OneTimePassword.js | |||
@@ -0,0 +1,350 @@ | |||
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.OneTimePassword = function(args) { | ||
32 | args = args || {}; | ||
33 | |||
34 | //this._user = args['user']; | ||
35 | this._reference = args['reference']|| Clipperz.PM.Crypto.randomKey(); | ||
36 | this._password = args['password']; | ||
37 | this._passwordValue = Clipperz.PM.DataModel.OneTimePassword.normalizedOneTimePassword(args['password']); | ||
38 | this._creationDate = args['created'] ? Clipperz.PM.Date.parseDateWithUTCFormat(args['created']) : new Date(); | ||
39 | this._usageDate = args['used'] ? Clipperz.PM.Date.parseDateWithUTCFormat(args['used']) : null; | ||
40 | |||
41 | this._status = args['status'] || 'ACTIVE'; //'REQUESTED', 'USED', 'DISABLED' | ||
42 | this._connectionInfo= null; | ||
43 | |||
44 | this._key = null; | ||
45 | this._keyChecksum= null; | ||
46 | |||
47 | return this; | ||
48 | } | ||
49 | |||
50 | Clipperz.PM.DataModel.OneTimePassword.prototype = MochiKit.Base.update(null, { | ||
51 | |||
52 | 'toString': function() { | ||
53 | return "Clipperz.PM.DataModel.OneTimePassword"; | ||
54 | }, | ||
55 | /* | ||
56 | //------------------------------------------------------------------------- | ||
57 | |||
58 | 'user': function() { | ||
59 | return this._user; | ||
60 | }, | ||
61 | |||
62 | //------------------------------------------------------------------------- | ||
63 | |||
64 | 'password': function() { | ||
65 | return this._password; | ||
66 | }, | ||
67 | |||
68 | //------------------------------------------------------------------------- | ||
69 | |||
70 | 'passwordValue': function() { | ||
71 | return this._passwordValue; | ||
72 | }, | ||
73 | |||
74 | //------------------------------------------------------------------------- | ||
75 | |||
76 | 'creationDate': function() { | ||
77 | return this._creationDate; | ||
78 | }, | ||
79 | |||
80 | //------------------------------------------------------------------------- | ||
81 | |||
82 | 'reference': function() { | ||
83 | return this._reference; | ||
84 | }, | ||
85 | |||
86 | //------------------------------------------------------------------------- | ||
87 | |||
88 | 'key': function() { | ||
89 | if (this._key == null) { | ||
90 | this._key = Clipperz.PM.DataModel.OneTimePassword.computeKeyWithUsernameAndPassword(this.user().username(), this.passwordValue()); | ||
91 | } | ||
92 | |||
93 | return this._key; | ||
94 | }, | ||
95 | |||
96 | //------------------------------------------------------------------------- | ||
97 | |||
98 | 'keyChecksum': function() { | ||
99 | if (this._keyChecksum == null) { | ||
100 | this._keyChecksum = Clipperz.PM.DataModel.OneTimePassword.computeKeyChecksumWithUsernameAndPassword(this.user().username(), this.passwordValue()); | ||
101 | } | ||
102 | |||
103 | return this._keyChecksum; | ||
104 | }, | ||
105 | */ | ||
106 | //------------------------------------------------------------------------- | ||
107 | |||
108 | 'status': function() { | ||
109 | return this._status; | ||
110 | }, | ||
111 | |||
112 | 'setStatus': function(aValue) { | ||
113 | this._status = aValue; | ||
114 | }, | ||
115 | |||
116 | //------------------------------------------------------------------------- | ||
117 | /* | ||
118 | 'serializedData': function() { | ||
119 | var result; | ||
120 | |||
121 | result = { | ||
122 | 'password': this.password(), | ||
123 | 'created': this.creationDate() ? Clipperz.PM.Date.formatDateWithUTCFormat(this.creationDate()) : null, | ||
124 | 'used': this.usageDate() ? Clipperz.PM.Date.formatDateWithUTCFormat(this.usageDate()) : null, | ||
125 | 'status': this.status() | ||
126 | }; | ||
127 | |||
128 | return result; | ||
129 | }, | ||
130 | |||
131 | //------------------------------------------------------------------------- | ||
132 | |||
133 | 'packedPassphrase': function() { | ||
134 | var result; | ||
135 | var packedPassphrase; | ||
136 | var encodedPassphrase; | ||
137 | varprefixPadding; | ||
138 | var suffixPadding; | ||
139 | var getRandomBytes; | ||
140 | |||
141 | getRandomBytes = MochiKit.Base.method(Clipperz.Crypto.PRNG.defaultRandomGenerator(), 'getRandomBytes'); | ||
142 | |||
143 | encodedPassphrase = new Clipperz.ByteArray(this.user().passphrase()).toBase64String(); | ||
144 | //Clipperz.logDebug("--- encodedPassphrase.length: " + encodedPassphrase.length); | ||
145 | prefixPadding = getRandomBytes(getRandomBytes(1).byteAtIndex(0)).toBase64String(); | ||
146 | //Clipperz.logDebug("--- prefixPadding.length: " + prefixPadding.length); | ||
147 | suffixPadding = getRandomBytes((500 - prefixPadding.length - encodedPassphrase.length) * 6 / 8).toBase64String(); | ||
148 | //Clipperz.logDebug("--- suffixPadding.length: " + suffixPadding.length); | ||
149 | //Clipperz.logDebug("--- total.length: " + (prefixPadding.length + encodedPassphrase.length + suffixPadding.length)); | ||
150 | |||
151 | packedPassphrase = { | ||
152 | 'prefix': prefixPadding, | ||
153 | 'passphrase': encodedPassphrase, | ||
154 | 'suffix': suffixPadding | ||
155 | }; | ||
156 | |||
157 | // result = Clipperz.Base.serializeJSON(packedPassphrase); | ||
158 | result = packedPassphrase; | ||
159 | //Clipperz.logDebug("===== OTP packedPassprase: [" + result.length + "]" + result); | ||
160 | //Clipperz.logDebug("<<< OneTimePassword.packedPassphrase"); | ||
161 | |||
162 | return result; | ||
163 | }, | ||
164 | |||
165 | //------------------------------------------------------------------------- | ||
166 | |||
167 | 'encryptedPackedPassphrase': function() { | ||
168 | return Clipperz.PM.Crypto.deferredEncryptWithCurrentVersion(this.passwordValue(), this.packedPassphrase()) | ||
169 | }, | ||
170 | |||
171 | //------------------------------------------------------------------------- | ||
172 | |||
173 | 'encryptedData': function() { | ||
174 | var deferredResult; | ||
175 | varresult; | ||
176 | |||
177 | //Clipperz.logDebug(">>> OneTimePassword.encryptedData"); | ||
178 | //Clipperz.logDebug("--- OneTimePassword.encryptedData - id: " + this.reference()); | ||
179 | result = { | ||
180 | 'reference': this.reference(), | ||
181 | 'key': this.key(), | ||
182 | 'keyChecksum': this.keyChecksum(), | ||
183 | 'data': "", | ||
184 | 'version': Clipperz.PM.Crypto.encryptingFunctions.currentVersion | ||
185 | } | ||
186 | //Clipperz.logDebug("--- OneTimePassword.encryptedData - 2: " + Clipperz.Base.serializeJSON(result)); | ||
187 | deferredResult = new MochiKit.Async.Deferred(); | ||
188 | //Clipperz.logDebug("--- OneTimePassword.encryptedData - 3"); | ||
189 | //deferredResult.addBoth(function(res) {Clipperz.logDebug("OneTimePassword.encryptedData - 1: " + res); return res;}); | ||
190 | //# deferredResult.addCallback(Clipperz.PM.Crypto.deferredEncryptWithCurrentVersion, this.passwordValue(), this.packedPassphrase()); | ||
191 | deferredResult.addCallback(MochiKit.Base.method(this, 'encryptedPackedPassphrase')); | ||
192 | //Clipperz.logDebug("--- OneTimePassword.encryptedData - 4"); | ||
193 | //deferredResult.addBoth(function(res) {Clipperz.logDebug("OneTimePassword.encryptedData - 2: [" + res.length + "]" + res); return res;}); | ||
194 | deferredResult.addCallback(function(aResult, res) { | ||
195 | aResult['data'] = res; | ||
196 | return aResult; | ||
197 | }, result); | ||
198 | //Clipperz.logDebug("--- OneTimePassword.encryptedData - 5"); | ||
199 | //deferredResult.addBoth(function(res) {Clipperz.logDebug("OneTimePassword.encryptedData - 3: " + Clipperz.Base.serializeJSON(res)); return res;}); | ||
200 | deferredResult.callback(); | ||
201 | //Clipperz.logDebug("--- OneTimePassword.encryptedData - 6"); | ||
202 | |||
203 | return deferredResult; | ||
204 | }, | ||
205 | |||
206 | //------------------------------------------------------------------------- | ||
207 | |||
208 | 'saveChanges': function() { | ||
209 | var deferredResult; | ||
210 | varresult; | ||
211 | |||
212 | //Clipperz.logDebug(">>> OneTimePassword.saveChanges"); | ||
213 | result = {}; | ||
214 | deferredResult = new MochiKit.Async.Deferred(); | ||
215 | |||
216 | deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'saveOTP_encryptUserData'); | ||
217 | deferredResult.addCallback(MochiKit.Base.method(this.user(), 'encryptedData')); | ||
218 | deferredResult.addCallback(function(aResult, res) { | ||
219 | aResult['user'] = res; | ||
220 | return aResult; | ||
221 | }, result); | ||
222 | |||
223 | deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'saveOTP_encryptOTPData'); | ||
224 | deferredResult.addCallback(MochiKit.Base.method(this, 'encryptedData')); | ||
225 | deferredResult.addCallback(function(aResult, res) { | ||
226 | aResult['oneTimePassword'] = res; | ||
227 | return aResult; | ||
228 | }, result); | ||
229 | |||
230 | deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'saveOTP_sendingData'); | ||
231 | //deferredResult.addBoth(function(res) {Clipperz.logDebug("OneTimePassword.saveChanges - 1: " + Clipperz.Base.serializeJSON(res)); return res;}); | ||
232 | deferredResult.addCallback(MochiKit.Base.method(this.user().connection(), 'message'), 'addNewOneTimePassword'); | ||
233 | |||
234 | deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'updatedProgressState', 'saveOTP_updatingInterface'); | ||
235 | //deferredResult.addBoth(function(res) {Clipperz.logDebug("OneTimePassword.saveChanges - 2: " + res); return res;}); | ||
236 | deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'notify', 'OTPUpdated'); | ||
237 | deferredResult.addCallback(Clipperz.NotificationCenter.deferredNotification, this, 'oneTimePassword_saveChanges_done', null); | ||
238 | //deferredResult.addBoth(function(res) {Clipperz.logDebug("OneTimePassword.saveChanges - 2: " + res); return res;}); | ||
239 | deferredResult.callback(); | ||
240 | //Clipperz.logDebug("<<< OneTimePassword.saveChanges"); | ||
241 | |||
242 | return deferredResult; | ||
243 | }, | ||
244 | |||
245 | //------------------------------------------------------------------------- | ||
246 | |||
247 | 'usageDate': function() { | ||
248 | return this._usageDate; | ||
249 | }, | ||
250 | |||
251 | 'setUsageDate': function(aValue) { | ||
252 | this._usageDate = aValue; | ||
253 | }, | ||
254 | |||
255 | //------------------------------------------------------------------------- | ||
256 | |||
257 | 'connectionInfo': function() { | ||
258 | return this._connectionInfo; | ||
259 | }, | ||
260 | |||
261 | 'setConnectionInfo': function(aValue) { | ||
262 | this._connectionInfo = aValue; | ||
263 | }, | ||
264 | |||
265 | //------------------------------------------------------------------------- | ||
266 | |||
267 | 'isExpired': function() { | ||
268 | return (this.usageDate() != null); | ||
269 | }, | ||
270 | |||
271 | //------------------------------------------------------------------------- | ||
272 | |||
273 | 'updateStatusWithValues': function(someValues) { | ||
274 | var result; | ||
275 | |||
276 | result = false; | ||
277 | |||
278 | if (someValues['status'] != this.status()) { | ||
279 | result = true; | ||
280 | } | ||
281 | |||
282 | this.setStatus(someValues['status']); | ||
283 | this.setUsageDate(Clipperz.PM.Date.parseDateWithUTCFormat(someValues['requestDate'])); | ||
284 | this.setConnectionInfo(someValues['connection']); | ||
285 | |||
286 | return result; | ||
287 | }, | ||
288 | */ | ||
289 | //------------------------------------------------------------------------- | ||
290 | __syntaxFix__: "syntax fix" | ||
291 | }); | ||
292 | |||
293 | //############################################################################# | ||
294 | |||
295 | Clipperz.PM.DataModel.OneTimePassword.computeKeyWithUsernameAndPassword = function(anUsername, aPassword) { | ||
296 | return Clipperz.Crypto.SHA.sha_d256(new Clipperz.ByteArray(aPassword)).toHexString().substring(2); | ||
297 | } | ||
298 | |||
299 | Clipperz.PM.DataModel.OneTimePassword.computeKeyChecksumWithUsernameAndPassword = function(anUsername, aPassword) { | ||
300 | return Clipperz.Crypto.SHA.sha_d256(new Clipperz.ByteArray(anUsername + aPassword)).toHexString().substring(2); | ||
301 | } | ||
302 | |||
303 | //============================================================================= | ||
304 | |||
305 | Clipperz.PM.DataModel.OneTimePassword.isValidOneTimePasswordValue = function(aPassword) { | ||
306 | var result; | ||
307 | |||
308 | //"yaxx k7ww - f8y6 tqz5 - 58b6 th44 - 9cwv q0fg" | ||
309 | if (aPassword.replace(/[\s\-]/g, '').length == 32) { | ||
310 | try { | ||
311 | var passwordByteArray; | ||
312 | |||
313 | passwordByteArray = new Clipperz.ByteArray(); | ||
314 | passwordByteArray.appendBase32String(aPassword); | ||
315 | |||
316 | result = true; | ||
317 | } catch(exception) { | ||
318 | result = false; | ||
319 | } | ||
320 | } else { | ||
321 | result = false; | ||
322 | } | ||
323 | |||
324 | return result; | ||
325 | } | ||
326 | |||
327 | //============================================================================= | ||
328 | |||
329 | Clipperz.PM.DataModel.OneTimePassword.normalizedOneTimePassword = function(aPassword) { | ||
330 | varresult; | ||
331 | |||
332 | if (aPassword.replace(/[\s\-]/g, '').length == 32) { | ||
333 | try { | ||
334 | var passwordByteArray; | ||
335 | |||
336 | passwordByteArray = new Clipperz.ByteArray(); | ||
337 | passwordByteArray.appendBase32String(aPassword); | ||
338 | |||
339 | result = passwordByteArray.toBase64String(); | ||
340 | } catch(exception) { | ||
341 | result = aPassword; | ||
342 | } | ||
343 | } else { | ||
344 | result = aPassword; | ||
345 | } | ||
346 | |||
347 | return result; | ||
348 | } | ||
349 | |||
350 | //############################################################################# | ||
diff --git a/frontend/delta/js/Clipperz/PM/DataModel/Record.Version.Field.js b/frontend/delta/js/Clipperz/PM/DataModel/Record.Version.Field.js new file mode 100644 index 0000000..01e7196 --- a/dev/null +++ b/frontend/delta/js/Clipperz/PM/DataModel/Record.Version.Field.js | |||
@@ -0,0 +1,186 @@ | |||
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 | try { if (typeof(Clipperz.PM.DataModel.Record.Version) == 'undefined') { throw ""; }} catch (e) { | ||
25 | throw "Clipperz.PM.DataModel.Record.Version.Field depends on Clipperz.PM.DataModel.Record.Version!"; | ||
26 | } | ||
27 | |||
28 | Clipperz.PM.DataModel.Record.Version.Field = function(args) { | ||
29 | Clipperz.PM.DataModel.Record.Version.Field.superclass.constructor.apply(this, arguments); | ||
30 | |||
31 | this._recordVersion = args.recordVersion|| Clipperz.Base.exception.raise('MandatoryParameter'); | ||
32 | this._reference = args.reference || Clipperz.PM.Crypto.randomKey(); | ||
33 | |||
34 | return this; | ||
35 | } | ||
36 | |||
37 | |||
38 | Clipperz.Base.extend(Clipperz.PM.DataModel.Record.Version.Field, Object, { | ||
39 | |||
40 | 'toString': function() { | ||
41 | return "Record.Version.Field (" + this.reference() + ")"; | ||
42 | }, | ||
43 | |||
44 | //------------------------------------------------------------------------- | ||
45 | |||
46 | 'recordVersion': function () { | ||
47 | return this._recordVersion; | ||
48 | }, | ||
49 | |||
50 | //------------------------------------------------------------------------- | ||
51 | |||
52 | 'reference': function () { | ||
53 | return this._reference; | ||
54 | }, | ||
55 | |||
56 | //------------------------------------------------------------------------- | ||
57 | |||
58 | 'getItem': function (aKey) { | ||
59 | return Clipperz.Async.callbacks("Clipperz.PM.DataModel.Record.Version.Field.getItem", [ | ||
60 | MochiKit.Base.method(this, 'recordVersion'), | ||
61 | MochiKit.Base.methodcaller('getValue', 'fields' + '.' + this.reference() + '.' + aKey) | ||
62 | ], {trace:false}); | ||
63 | }, | ||
64 | |||
65 | 'setItem': function (aKey, aValue) { | ||
66 | return Clipperz.Async.callbacks("Clipperz.PM.DataModel.Record.Version.Field.getItem", [ | ||
67 | MochiKit.Base.method(this, 'recordVersion'), | ||
68 | MochiKit.Base.methodcaller('setValue', 'fields' + '.' + this.reference() + '.' + aKey, aValue) | ||
69 | ], {trace:false}); | ||
70 | }, | ||
71 | |||
72 | //------------------------------------------------------------------------- | ||
73 | |||
74 | 'label': function () { | ||
75 | return this.getItem('label'); | ||
76 | }, | ||
77 | |||
78 | 'setLabel': function (aValue) { | ||
79 | return this.setItem('label', aValue); | ||
80 | }, | ||
81 | |||
82 | //------------------------------------------------------------------------- | ||
83 | |||
84 | 'value': function () { | ||
85 | return this.getItem('value'); | ||
86 | }, | ||
87 | |||
88 | 'setValue': function (aValue) { | ||
89 | return this.setItem('value', aValue); | ||
90 | }, | ||
91 | |||
92 | //------------------------------------------------------------------------- | ||
93 | |||
94 | 'actionType': function () { | ||
95 | return Clipperz.Async.callbacks("Clipperz.PM.DataModel.Record.Version.Field.actionType", [ | ||
96 | Clipperz.Async.collectResults("Clipperz.PM.DataModel.Record.Version.Field.actionType [collect results]", { | ||
97 | 'isHidden':MochiKit.Base.method(this, 'isHidden'), | ||
98 | 'value':MochiKit.Base.method(this, 'value') | ||
99 | }, {trace:false}), | ||
100 | function (someValues) { | ||
101 | var result; //'NONE', 'URL', 'EMAIL', 'PASSWORD' | ||
102 | |||
103 | result = 'NONE'; | ||
104 | |||
105 | if (someValues['isHidden']) { | ||
106 | result = 'PASSWORD'; | ||
107 | } else if (Clipperz.Base.isUrl(someValues['value'])) { | ||
108 | result = 'URL' | ||
109 | } else if (Clipperz.Base.isEmail(someValues['value'])) { | ||
110 | result = 'EMAIL' | ||
111 | }; | ||
112 | |||
113 | return result; | ||
114 | } | ||
115 | ], {trace:false}); | ||
116 | }, | ||
117 | |||
118 | //------------------------------------------------------------------------- | ||
119 | |||
120 | 'isHidden': function () { | ||
121 | return this.getItem('hidden'); | ||
122 | }, | ||
123 | |||
124 | 'setIsHidden': function (aValue) { | ||
125 | return this.setItem('hidden', aValue); | ||
126 | }, | ||
127 | |||
128 | //------------------------------------------------------------------------- | ||
129 | |||
130 | 'isEmpty': function () { | ||
131 | var deferredResult; | ||
132 | |||
133 | deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.Record.Version.Field.isEmpty", {trace:false}); | ||
134 | |||
135 | deferredResult.collectResults({ | ||
136 | 'label': [ | ||
137 | MochiKit.Base.method(this, 'label'), | ||
138 | MochiKit.Base.partial(MochiKit.Base.operator.eq, '') | ||
139 | ], | ||
140 | 'value': [ | ||
141 | MochiKit.Base.method(this, 'value'), | ||
142 | MochiKit.Base.partial(MochiKit.Base.operator.eq, '') | ||
143 | ], | ||
144 | 'isHidden': [ | ||
145 | MochiKit.Base.method(this, 'isHidden'), | ||
146 | MochiKit.Base.partial(MochiKit.Base.operator.eq, false) | ||
147 | ] | ||
148 | }); | ||
149 | deferredResult.addCallback(MochiKit.Base.values); | ||
150 | deferredResult.addCallback(function(someValues) { | ||
151 | return MochiKit.Iter.every(someValues, MochiKit.Base.operator.identity); | ||
152 | }); | ||
153 | deferredResult.callback(); | ||
154 | |||
155 | return deferredResult; | ||
156 | }, | ||
157 | |||
158 | //------------------------------------------------------------------------- | ||
159 | |||
160 | 'content': function () { | ||
161 | var deferredResult; | ||
162 | varfieldValues; | ||
163 | |||
164 | fieldValues = {}; | ||
165 | deferredResult = new Clipperz.Async.Deferred("Record.Version.Field.content", {trace:false}); | ||
166 | deferredResult.addMethod(this, 'reference'); | ||
167 | deferredResult.addCallback(function (aValue) { fieldValues['reference'] = aValue; }); | ||
168 | deferredResult.addMethod(this, 'label'); | ||
169 | deferredResult.addCallback(function (aValue) { fieldValues['label'] = aValue; }); | ||
170 | deferredResult.addMethod(this, 'value'); | ||
171 | deferredResult.addCallback(function (aValue) { fieldValues['value'] = aValue; }); | ||
172 | deferredResult.addMethod(this, 'actionType'); | ||
173 | deferredResult.addCallback(function (aValue) { fieldValues['actionType'] = aValue; }); | ||
174 | deferredResult.addMethod(this, 'isHidden'); | ||
175 | deferredResult.addCallback(function (aValue) { fieldValues['isHidden'] = aValue; }); | ||
176 | deferredResult.addCallback(function () { return fieldValues; }); | ||
177 | deferredResult.callback(); | ||
178 | |||
179 | return deferredResult; | ||
180 | }, | ||
181 | |||
182 | //------------------------------------------------------------------------- | ||
183 | __syntaxFix__: "syntax fix" | ||
184 | }); | ||
185 | |||
186 | |||
diff --git a/frontend/delta/js/Clipperz/PM/DataModel/Record.Version.js b/frontend/delta/js/Clipperz/PM/DataModel/Record.Version.js new file mode 100644 index 0000000..87b319c --- a/dev/null +++ b/frontend/delta/js/Clipperz/PM/DataModel/Record.Version.js | |||
@@ -0,0 +1,328 @@ | |||
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 | try { if (typeof(Clipperz.PM.DataModel.Record) == 'undefined') { throw ""; }} catch (e) { | ||
25 | throw "Clipperz.PM.DataModel.Record.Version depends on Clipperz.PM.DataModel.Record!"; | ||
26 | } | ||
27 | |||
28 | Clipperz.PM.DataModel.Record.Version = function(args) { | ||
29 | Clipperz.PM.DataModel.Record.Version.superclass.constructor.apply(this, arguments); | ||
30 | |||
31 | this._getVersionFunction = args.getVersion|| Clipperz.Base.exception.raise('MandatoryParameter'); | ||
32 | this._fields = null; | ||
33 | |||
34 | return this; | ||
35 | } | ||
36 | |||
37 | |||
38 | Clipperz.Base.extend(Clipperz.PM.DataModel.Record.Version, Clipperz.PM.DataModel.EncryptedRemoteObject, { | ||
39 | |||
40 | 'toString': function() { | ||
41 | return "Record.Version (" + this.reference() + ")"; | ||
42 | }, | ||
43 | |||
44 | //------------------------------------------------------------------------- | ||
45 | |||
46 | 'reference': function () { | ||
47 | return this._reference; | ||
48 | }, | ||
49 | |||
50 | //------------------------------------------------------------------------- | ||
51 | /* | ||
52 | 'hasPendingChanges': function () { | ||
53 | var deferredResult; | ||
54 | |||
55 | deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.Record.Version.hasPendingChanges", {trace:false}); | ||
56 | deferredResult.addCallback(MochiKit.Base.bind(Clipperz.PM.DataModel.Record.Version.superclass.hasPendingChanges, this)); | ||
57 | deferredResult.callback(); | ||
58 | |||
59 | return deferredResult; | ||
60 | }, | ||
61 | */ | ||
62 | //------------------------------------------------------------------------- | ||
63 | |||
64 | |||
65 | 'hasPendingChangesWhenBrandNew': function () { | ||
66 | var deferredResult; | ||
67 | |||
68 | deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.Record.Version.hasPendingChangesWhenBrandNew", {trace:false}); | ||
69 | deferredResult.addMethod(this, 'fields'); | ||
70 | deferredResult.addCallback(MochiKit.Base.values); | ||
71 | deferredResult.addCallback(MochiKit.Base.map, MochiKit.Base.methodcaller('isEmpty')) | ||
72 | deferredResult.addCallback(Clipperz.Async.collectAll); | ||
73 | deferredResult.addCallback(function(someValues) { | ||
74 | return MochiKit.Iter.every(someValues, MochiKit.Base.operator.identity); | ||
75 | }); | ||
76 | deferredResult.addCallback(MochiKit.Base.operator.lognot) | ||
77 | deferredResult.callback(); | ||
78 | |||
79 | return deferredResult; | ||
80 | }, | ||
81 | |||
82 | //========================================================================= | ||
83 | |||
84 | 'commitTransientState': function () { | ||
85 | var deferredResult; | ||
86 | |||
87 | deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.Record.Version.commitTransientState", {trace:false}); | ||
88 | deferredResult.addCallback(MochiKit.Base.bind(Clipperz.PM.DataModel.Record.Version.superclass.commitTransientState, this)); | ||
89 | deferredResult.callback(); | ||
90 | |||
91 | return deferredResult; | ||
92 | }, | ||
93 | |||
94 | //========================================================================= | ||
95 | |||
96 | 'unpackData': function (someData) { //++ | ||
97 | varresult; | ||
98 | |||
99 | result = someData; | ||
100 | if ((someData['fields'] != null) && (someData['fields'] instanceof Array)) { | ||
101 | varfields; | ||
102 | var i,c; | ||
103 | |||
104 | fields = someData['fields']; | ||
105 | delete someData['fields']; | ||
106 | |||
107 | someData['fields'] = {}; | ||
108 | c = fields.length; | ||
109 | for (i=0; i<c; i++) { | ||
110 | someData['fields'][i] = fields[i]; | ||
111 | } | ||
112 | } | ||
113 | |||
114 | |||
115 | |||
116 | return result; | ||
117 | }, | ||
118 | |||
119 | //========================================================================= | ||
120 | |||
121 | 'fields': function () { | ||
122 | vardeferredResult; | ||
123 | var deferredLock; | ||
124 | |||
125 | deferredLock = this.getDeferredLockForKey('fields'); | ||
126 | |||
127 | deferredResult = new Clipperz.Async.Deferred("Record.Version.fields", {trace:false}); | ||
128 | deferredResult.acquireLock(deferredLock); | ||
129 | deferredResult.addCallback(MochiKit.Base.bind(function () { | ||
130 | var innerDeferredResult; | ||
131 | |||
132 | if (this._fields == null) { | ||
133 | innerDeferredResult = new Clipperz.Async.Deferred("Record.Version.fields <inner deferred>", {trace:false}); | ||
134 | innerDeferredResult.addMethod(this, 'getValue', 'fields'); | ||
135 | innerDeferredResult.addCallback(MochiKit.Base.bind(function (someObjectData) { | ||
136 | var reference; | ||
137 | |||
138 | this._fields = {}; | ||
139 | |||
140 | for (reference in someObjectData) { | ||
141 | varrecordVersionField; | ||
142 | |||
143 | recordVersionField = new Clipperz.PM.DataModel.Record.Version.Field({ | ||
144 | 'recordVersion':this, | ||
145 | 'reference': reference | ||
146 | }); | ||
147 | |||
148 | this._fields[reference] = recordVersionField; | ||
149 | } | ||
150 | |||
151 | return this._fields; | ||
152 | }, this)); | ||
153 | innerDeferredResult.callback(); | ||
154 | } else { | ||
155 | innerDeferredResult = MochiKit.Async.succeed(this._fields); | ||
156 | } | ||
157 | |||
158 | return innerDeferredResult; | ||
159 | }, this)); | ||
160 | deferredResult.releaseLock(deferredLock); | ||
161 | deferredResult.callback(); | ||
162 | |||
163 | return deferredResult; | ||
164 | }, | ||
165 | |||
166 | //------------------------------------------------------------------------- | ||
167 | |||
168 | 'getFieldsValues': function () { | ||
169 | return this.getValue('fields'); | ||
170 | }, | ||
171 | |||
172 | //------------------------------------------------------------------------- | ||
173 | |||
174 | 'addField': function (someParameters) { | ||
175 | varnewField; | ||
176 | |||
177 | newField = new Clipperz.PM.DataModel.Record.Version.Field({recordVersion:this}); | ||
178 | |||
179 | return Clipperz.Async.callbacks("Record.Version.addField", [ | ||
180 | MochiKit.Base.method(this, 'fields'), | ||
181 | |||
182 | MochiKit.Base.method(this, '_getObjectDataStore'), | ||
183 | MochiKit.Base.methodcaller('values'), | ||
184 | Clipperz.Base.serializeJSON, | ||
185 | |||
186 | MochiKit.Base.bind(function () { this._fields[newField.reference()] = newField; }, this), | ||
187 | MochiKit.Base.method(newField, 'setLabel', someParameters['label']), | ||
188 | MochiKit.Base.method(newField, 'setValue', someParameters['value']), | ||
189 | MochiKit.Base.method(newField, 'setIsHidden',someParameters['isHidden']), | ||
190 | |||
191 | MochiKit.Base.method(this, '_getObjectDataStore'), | ||
192 | MochiKit.Base.methodcaller('values'), | ||
193 | Clipperz.Base.serializeJSON, | ||
194 | |||
195 | MochiKit.Base.partial(MochiKit.Async.succeed, newField) | ||
196 | ], {trace:false}); | ||
197 | }, | ||
198 | |||
199 | //------------------------------------------------------------------------- | ||
200 | |||
201 | 'removeField': function (aField) { | ||
202 | return Clipperz.Async.callbacks("Record.Version.removeField", [ | ||
203 | MochiKit.Base.method(this, 'fields'), | ||
204 | MochiKit.Base.bind(function () { delete this._fields[aField.reference()]; }, this), | ||
205 | MochiKit.Base.method(this, 'removeValue', 'fields' + '.' + aField.reference()) | ||
206 | ], {trace:false}); | ||
207 | }, | ||
208 | |||
209 | //------------------------------------------------------------------------- | ||
210 | /* | ||
211 | 'sortFieldReference': function (someSortedFieldReferences) { | ||
212 | |||
213 | |||
214 | |||
215 | }, | ||
216 | */ | ||
217 | //========================================================================= | ||
218 | /* | ||
219 | 'directLogins': function () { | ||
220 | return MochiKit.Base.values(this._directLogins); | ||
221 | }, | ||
222 | |||
223 | 'addDirectLogin': function (aDirectLogin) { | ||
224 | this._directLogins[aDirectLogin.reference()] = aDirectLogin; | ||
225 | }, | ||
226 | */ | ||
227 | |||
228 | //========================================================================= | ||
229 | /* | ||
230 | 'updateValues': function (anotherVersion) { | ||
231 | return Clipperz.Async.callbacks("Record.Version.updateValue", [ | ||
232 | MochiKit.Base.partial(MochiKit.Async.succeed, this) | ||
233 | ], {trace:false}); | ||
234 | }, | ||
235 | */ | ||
236 | //========================================================================= | ||
237 | |||
238 | 'setRemoteData': function (aValue) { | ||
239 | this._remoteData = aValue; | ||
240 | |||
241 | return aValue; | ||
242 | }, | ||
243 | |||
244 | //========================================================================= | ||
245 | |||
246 | 'getVersionFunction': function () { | ||
247 | return this._getVersionFunction; | ||
248 | }, | ||
249 | |||
250 | 'previousVersion': function () { | ||
251 | return Clipperz.Async.callbacks("Record.Versions.previousVersion", [ | ||
252 | MochiKit.Base.method(this, 'previousVersionReference'), | ||
253 | this.getVersionFunction() | ||
254 | ], {trace:false}); | ||
255 | }, | ||
256 | |||
257 | 'previousVersionReference': function () { | ||
258 | return this.getValue('previousVersionReference'); | ||
259 | }, | ||
260 | |||
261 | 'previousVersionKey': function () { | ||
262 | //TODO: this value i encrypted on its own. So it can not be saved in the main objectStore!!! | ||
263 | return this.getValue('previousVersionKey'); | ||
264 | }, | ||
265 | |||
266 | //------------------------------------------------------------------------- | ||
267 | |||
268 | 'setPreviousVersionReferenceAndKey': function (aVersionObjectAndKey) { | ||
269 | // this._previousVersion = anotherVersion; | ||
270 | return Clipperz.Async.callbacks("Record.Version.setPreviousVersion", [ | ||
271 | MochiKit.Base.method(this, 'setValue', 'previousVersionReference',aVersionObjectAndKey['reference']), | ||
272 | MochiKit.Base.method(this, 'setValue', 'previousVersionKey', aVersionObjectAndKey['key']) | ||
273 | ], {trace:false}); | ||
274 | }, | ||
275 | |||
276 | //========================================================================= | ||
277 | |||
278 | 'revertChanges': function () { | ||
279 | this.setReference(this.transientState()['originalReference']); | ||
280 | Clipperz.PM.DataModel.Record.Version.superclass.revertChanges.apply(this, arguments); | ||
281 | }, | ||
282 | |||
283 | //------------------------------------------------------------------------- | ||
284 | |||
285 | 'prepareRemoteDataWithKey': function (aKey) { | ||
286 | var deferredResult; | ||
287 | var result; | ||
288 | |||
289 | result = {}; | ||
290 | |||
291 | deferredResult = new Clipperz.Async.Deferred("Record.Version.prepareRemoteDataWithKey", {trace:false}); | ||
292 | if (this.isBrandNew() == false) { | ||
293 | this.transientState()['originalReference'] = this.reference(); | ||
294 | |||
295 | deferredResult.collectResults({ | ||
296 | 'key':MochiKit.Base.partial(MochiKit.Async.succeed, aKey), | ||
297 | 'value': MochiKit.Base.method(this, 'getKey'), | ||
298 | 'version': MochiKit.Base.partial(MochiKit.Async.succeed, Clipperz.PM.Crypto.encryptingFunctions.currentVersion) | ||
299 | }); | ||
300 | deferredResult.addCallback(Clipperz.PM.Crypto.deferredEncrypt); | ||
301 | deferredResult.addCallback(Clipperz.Async.setItem, result, 'previousVersionKey'); | ||
302 | } else { | ||
303 | deferredResult.addCallback(Clipperz.Async.setItem, result, 'previousVersionKey', Clipperz.PM.Crypto.nullValue); | ||
304 | } | ||
305 | deferredResult.addCallback(MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.prepareRemoteDataWithKey, this, aKey)); | ||
306 | deferredResult.addCallback(MochiKit.Base.update, result); | ||
307 | deferredResult.addMethod(this, 'setRemoteData'); | ||
308 | |||
309 | deferredResult.callback(); | ||
310 | |||
311 | return deferredResult; | ||
312 | }, | ||
313 | |||
314 | //========================================================================= | ||
315 | /* | ||
316 | 'deleteAllCleanTextData': function () { | ||
317 | return Clipperz.PM.DataModel.Record.Version.superclass.deleteAllCleanTextData.apply(this, arguments); | ||
318 | }, | ||
319 | |||
320 | 'hasAnyCleanTextData': function () { | ||
321 | return Clipperz.PM.DataModel.Record.Version.superclass.hasAnyCleanTextData.apply(this, arguments); | ||
322 | }, | ||
323 | */ | ||
324 | //========================================================================= | ||
325 | __syntaxFix__: "syntax fix" | ||
326 | }); | ||
327 | |||
328 | |||
diff --git a/frontend/delta/js/Clipperz/PM/DataModel/Record.js b/frontend/delta/js/Clipperz/PM/DataModel/Record.js new file mode 100644 index 0000000..379872a --- a/dev/null +++ b/frontend/delta/js/Clipperz/PM/DataModel/Record.js | |||
@@ -0,0 +1,891 @@ | |||
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 | Clipperz.PM.DataModel.Record = function(args) { | ||
30 | Clipperz.PM.DataModel.Record.superclass.constructor.apply(this, arguments); | ||
31 | |||
32 | this._updateDate = (args.updateDate ? Clipperz.PM.Date.parse(args.updateDate) : Clipperz.Base.exception.raise('MandatoryParameter')); | ||
33 | |||
34 | this._retrieveIndexDataFunction = args.retrieveIndexDataFunction|| Clipperz.Base.exception.raise('MandatoryParameter'); | ||
35 | this._updateIndexDataFunction = args.updateIndexDataFunction || Clipperz.Base.exception.raise('MandatoryParameter'); | ||
36 | |||
37 | this._retrieveDirectLoginIndexDataFunction = args.retrieveDirectLoginIndexDataFunction|| null; | ||
38 | this._setDirectLoginIndexDataFunction = args.setDirectLoginIndexDataFunction || null; | ||
39 | this._removeDirectLoginIndexDataFunction = args.removeDirectLoginIndexDataFunction|| null; | ||
40 | |||
41 | this._createNewDirectLoginFunction = args.createNewDirectLoginFunction || null; | ||
42 | |||
43 | this._directLogins = {}; | ||
44 | |||
45 | this._versions = {}; | ||
46 | |||
47 | this._currentRecordVersion = null; | ||
48 | if (this.isBrandNew()) { | ||
49 | var newVersion; | ||
50 | |||
51 | this.setNotes(''); | ||
52 | newVersion = new Clipperz.PM.DataModel.Record.Version({ | ||
53 | 'retrieveKeyFunction':MochiKit.Base.method(this, 'getVersionKey'), | ||
54 | 'getVersion': MochiKit.Base.method(this, 'getVersion') | ||
55 | |||
56 | }); | ||
57 | this._versions[newVersion.reference()] = newVersion; | ||
58 | this._currentVersionReference = newVersion.reference(); | ||
59 | // this.setLabel(''); | ||
60 | } | ||
61 | |||
62 | return this; | ||
63 | } | ||
64 | |||
65 | |||
66 | Clipperz.Base.extend(Clipperz.PM.DataModel.Record, Clipperz.PM.DataModel.EncryptedRemoteObject, { | ||
67 | |||
68 | 'toString': function() { | ||
69 | return "Record (" + this.reference() + ")"; | ||
70 | }, | ||
71 | |||
72 | //------------------------------------------------------------------------- | ||
73 | |||
74 | 'reference': function () { | ||
75 | return this._reference; | ||
76 | }, | ||
77 | |||
78 | //========================================================================= | ||
79 | |||
80 | 'getIndexData': function () { | ||
81 | return this._retrieveIndexDataFunction(this.reference()); | ||
82 | }, | ||
83 | |||
84 | //......................................................................... | ||
85 | |||
86 | 'getIndexDataForKey': function (aKey) { | ||
87 | return Clipperz.Async.callbacks("Record.getIndexDataForKey", [ | ||
88 | MochiKit.Base.method(this, 'getIndexData'), | ||
89 | MochiKit.Base.itemgetter(aKey) | ||
90 | ], {trace:false}); | ||
91 | }, | ||
92 | |||
93 | //------------------------------------------------------------------------- | ||
94 | |||
95 | 'setIndexDataForKey': function (aKey, aValue) { | ||
96 | // return this._updateIndexDataFunction(this.reference(), aKey, aValue); | ||
97 | |||
98 | var deferredResult; | ||
99 | |||
100 | deferredResult = new Clipperz.Async.Deferred("Record.setIndexDataForKey", {trace:false}); | ||
101 | deferredResult.addMethod(this, 'getIndexDataForKey', aKey); | ||
102 | deferredResult.addCallback(MochiKit.Base.bind(function (aCurrentValue) { | ||
103 | var result; | ||
104 | var originalValue; | ||
105 | |||
106 | originalValue = this.transientState().getValue('originalValues.indexData.' + aKey); | ||
107 | if (originalValue == null) { | ||
108 | originalValue = this.transientState().setValue('originalValues.indexData.' + aKey, aCurrentValue); | ||
109 | } | ||
110 | |||
111 | if (aCurrentValue != aValue) { | ||
112 | if (originalValue != aValue) { | ||
113 | this.transientState().setValue('hasPendingChanges.indexData.' + aKey, true); | ||
114 | } else { | ||
115 | this.transientState().setValue('hasPendingChanges.indexData.' + aKey, false); | ||
116 | } | ||
117 | |||
118 | result = this._updateIndexDataFunction(this.reference(), aKey, aValue); | ||
119 | } else { | ||
120 | result = MochiKit.Async.succeed(aValue); | ||
121 | } | ||
122 | |||
123 | return result; | ||
124 | }, this)); | ||
125 | |||
126 | deferredResult.callback(); | ||
127 | |||
128 | return deferredResult; | ||
129 | }, | ||
130 | |||
131 | //========================================================================= | ||
132 | /* | ||
133 | 'key': function () { | ||
134 | return this.getIndexDataForKey('key'); | ||
135 | }, | ||
136 | */ | ||
137 | //========================================================================= | ||
138 | |||
139 | 'label': function () { | ||
140 | return this.getIndexDataForKey('label'); | ||
141 | }, | ||
142 | |||
143 | //......................................................................... | ||
144 | |||
145 | 'setLabel': function (aValue) { | ||
146 | return this.setIndexDataForKey('label', aValue); | ||
147 | }, | ||
148 | |||
149 | //========================================================================= | ||
150 | |||
151 | 'headerNotes': function () { | ||
152 | return this.getIndexDataForKey('notes'); | ||
153 | }, | ||
154 | |||
155 | //------------------------------------------------------------------------- | ||
156 | |||
157 | 'notes': function () { | ||
158 | return Clipperz.Async.callbacks("Record.notes", [ | ||
159 | MochiKit.Base.method(this, 'headerNotes'), | ||
160 | MochiKit.Base.bind(function (someHeaderNotes) { | ||
161 | var result; | ||
162 | |||
163 | if ((someHeaderNotes == null) || (typeof(someHeaderNotes) == 'undefined')) { | ||
164 | result = this.getValue('notes'); | ||
165 | } else { | ||
166 | result = MochiKit.Async.succeed(someHeaderNotes); | ||
167 | } | ||
168 | |||
169 | return result; | ||
170 | }, this) | ||
171 | ], {trace:false}); | ||
172 | }, | ||
173 | |||
174 | //......................................................................... | ||
175 | |||
176 | 'setNotes': function (aValue) { | ||
177 | return this.setValue('notes', aValue); | ||
178 | }, | ||
179 | |||
180 | //========================================================================= | ||
181 | |||
182 | 'updateDate': function () { | ||
183 | return MochiKit.Async.succeed(this._updateDate); | ||
184 | }, | ||
185 | |||
186 | //========================================================================= | ||
187 | |||
188 | 'favicon': function () { | ||
189 | var result; | ||
190 | var directLogins; | ||
191 | |||
192 | directLogins = MochiKit.Base.values(this.directLogins()); | ||
193 | if (directLogins.length > 0) { | ||
194 | result = directLogins[0].favicon(); | ||
195 | // } else if (/* is there an URL to use for searching a favicon */){ | ||
196 | } else { | ||
197 | result = null; //MochiKit.Async.succeed(Clipperz.PM.Strings['defaultFaviconUrl']); | ||
198 | } | ||
199 | |||
200 | return result; | ||
201 | }, | ||
202 | |||
203 | //------------------------------------------------------------------------- | ||
204 | |||
205 | 'searchableContent': function () { | ||
206 | var deferredResult; | ||
207 | |||
208 | deferredResult = new Clipperz.Async.Deferred("Record.searchableContent", {trace:false}); | ||
209 | |||
210 | deferredResult.collectResults({ | ||
211 | 'recordLabel': MochiKit.Base.method(this, 'label'), | ||
212 | 'directLoginLabels': [ | ||
213 | MochiKit.Base.method(this, 'directLoginReferences'), | ||
214 | MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.itemgetter('label')) | ||
215 | ] | ||
216 | }) | ||
217 | deferredResult.addCallback(function (someValues) { | ||
218 | return someValues['recordLabel'] + ' ' + someValues['directLoginLabels'].join(' '); | ||
219 | }); | ||
220 | deferredResult.callback(); | ||
221 | |||
222 | return deferredResult; | ||
223 | }, | ||
224 | |||
225 | //------------------------------------------------------------------------- | ||
226 | |||
227 | 'isMatching': function (aRegExp) { | ||
228 | return Clipperz.Async.callbacks("deferredFilterFunction", [ | ||
229 | MochiKit.Base.method(this, 'searchableContent'), | ||
230 | MochiKit.Base.method(aRegExp, 'test'), | ||
231 | function (doesItMatch) { | ||
232 | var result; | ||
233 | |||
234 | if (doesItMatch) { | ||
235 | result = MochiKit.Async.succeed('match'); | ||
236 | } else { | ||
237 | result = MochiKit.Async.fail('miss'); | ||
238 | } | ||
239 | |||
240 | return result; | ||
241 | } | ||
242 | ], {trace:false}); | ||
243 | }, | ||
244 | |||
245 | //========================================================================= | ||
246 | |||
247 | 'content': function () { | ||
248 | var deferredResult; | ||
249 | varresult; | ||
250 | |||
251 | result = { | ||
252 | 'fields': [], | ||
253 | 'directLogins': [] | ||
254 | }; | ||
255 | |||
256 | deferredResult = new Clipperz.Async.Deferred("Record.content", {trace:false}); | ||
257 | deferredResult.addMethod(this, 'reference'); | ||
258 | deferredResult.addCallback(function (aValue) { result['reference'] = aValue; }); | ||
259 | deferredResult.addMethod(this, 'label'); | ||
260 | deferredResult.addCallback(function (aValue) { result['title'] = aValue; }); | ||
261 | deferredResult.addMethod(this, 'notes'); | ||
262 | deferredResult.addCallback(function (aValue) { result['notes'] = aValue; }); | ||
263 | |||
264 | deferredResult.addMethod(this, 'fields'); | ||
265 | deferredResult.addCallback(MochiKit.Base.values); | ||
266 | deferredResult.addCallback(MochiKit.Base.map, MochiKit.Base.methodcaller('content')); | ||
267 | deferredResult.addCallback(Clipperz.Async.collectAll); | ||
268 | deferredResult.addCallback(MochiKit.Base.map, function (aValue) { result['fields'].push(aValue); }); | ||
269 | |||
270 | deferredResult.addMethod(this, 'directLogins'); | ||
271 | deferredResult.addCallback(MochiKit.Base.values); | ||
272 | deferredResult.addCallback(MochiKit.Base.map, MochiKit.Base.methodcaller('content')); | ||
273 | deferredResult.addCallback(Clipperz.Async.collectAll); | ||
274 | deferredResult.addCallback(MochiKit.Base.map, function (aValue) { result['directLogins'].push(aValue); }); | ||
275 | deferredResult.addCallback(function () { return result; }); | ||
276 | |||
277 | deferredResult.callback(); | ||
278 | |||
279 | return deferredResult; | ||
280 | }, | ||
281 | |||
282 | //========================================================================= | ||
283 | |||
284 | 'directLogins': function () { | ||
285 | return this._directLogins; | ||
286 | }, | ||
287 | |||
288 | 'addDirectLogin': function (aDirectLogin) { | ||
289 | this._directLogins[aDirectLogin.reference()] = aDirectLogin; | ||
290 | }, | ||
291 | |||
292 | 'directLoginWithReference': function (aDirectLoginReference) { | ||
293 | return this._directLogins[aDirectLoginReference]; | ||
294 | }, | ||
295 | |||
296 | 'createNewDirectLoginFunction': function () { | ||
297 | return this._createNewDirectLoginFunction; | ||
298 | }, | ||
299 | |||
300 | 'saveOriginalDirectLoginStatusToTransientState': function () { | ||
301 | if (this.transientState().getValue('directLogins') == null) { | ||
302 | // this.transientState().setValue('directLogins', this._directLogins) | ||
303 | MochiKit.Iter.forEach(MochiKit.Base.keys(this._directLogins), MochiKit.Base.bind(function(aKey) { | ||
304 | this.transientState().setValue('directLogins' + '.' + aKey, this._directLogins[aKey]) | ||
305 | }, this)) | ||
306 | } | ||
307 | }, | ||
308 | |||
309 | 'createNewDirectLogin': function () { | ||
310 | this.saveOriginalDirectLoginStatusToTransientState(); | ||
311 | |||
312 | return this.createNewDirectLoginFunction()(this); | ||
313 | }, | ||
314 | |||
315 | 'removeDirectLogin': function(aDirectLogin) { | ||
316 | this.saveOriginalDirectLoginStatusToTransientState(); | ||
317 | |||
318 | return Clipperz.Async.callbacks("Record.removeDirectLogin", [ | ||
319 | MochiKit.Base.method(this, 'removeValue', 'directLogins' + '.' + aDirectLogin.reference()), | ||
320 | MochiKit.Base.bind(function () { | ||
321 | delete this._directLogins[aDirectLogin.reference()] | ||
322 | }, this) | ||
323 | ], {trace:false}); | ||
324 | |||
325 | }, | ||
326 | |||
327 | 'directLoginReferences': function () { | ||
328 | var result; | ||
329 | |||
330 | result = Clipperz.Async.callbacks("Record.directLoginReferences", [ | ||
331 | MochiKit.Base.method(this, 'directLogins'), | ||
332 | MochiKit.Base.values, | ||
333 | function (someDirectLogins) { | ||
334 | var result; | ||
335 | var i,c; | ||
336 | |||
337 | result = []; | ||
338 | c = someDirectLogins.length; | ||
339 | for (i=0; i<c; i++) { | ||
340 | result.push(Clipperz.Async.collectResults("Record.directLoginReferences - collectResults", { | ||
341 | '_rowObject': MochiKit.Async.succeed, | ||
342 | '_reference': MochiKit.Base.methodcaller('reference'), | ||
343 | 'label': MochiKit.Base.methodcaller('label'), | ||
344 | 'favicon': MochiKit.Base.methodcaller('favicon') | ||
345 | }, {trace:false})(someDirectLogins[i])); | ||
346 | }; | ||
347 | |||
348 | return result; | ||
349 | }, | ||
350 | Clipperz.Async.collectAll | ||
351 | ], {trace:false}); | ||
352 | |||
353 | return result; | ||
354 | }, | ||
355 | |||
356 | //========================================================================= | ||
357 | |||
358 | 'unpackRemoteData': function (someData) { | ||
359 | var result; | ||
360 | |||
361 | /* | ||
362 | this._currentRecordVersion = new Clipperz.PM.DataModel.Record.Version({ | ||
363 | 'reference': someData['currentVersion']['reference'], | ||
364 | 'retrieveKeyFunction': MochiKit.Base.method(this, 'getCurrentRecordVersionKey'), | ||
365 | 'remoteData': someData['currentVersion'], | ||
366 | }); | ||
367 | */ | ||
368 | var versionKey; | ||
369 | |||
370 | for (versionKey in someData['versions']) { | ||
371 | this._versions[versionKey] = new Clipperz.PM.DataModel.Record.Version({ | ||
372 | 'reference': versionKey, | ||
373 | 'retrieveKeyFunction':MochiKit.Base.method(this, 'getVersionKey'), | ||
374 | 'remoteData': someData['versions'][versionKey], | ||
375 | 'getVersion': MochiKit.Base.method(this, 'getVersion') | ||
376 | }) | ||
377 | } | ||
378 | |||
379 | // this._currentVersionReference = someData['currentVersion']['reference']; | ||
380 | this._currentVersionReference = someData['currentVersion']; | ||
381 | |||
382 | result = Clipperz.PM.DataModel.Record.superclass.unpackRemoteData.apply(this, arguments); | ||
383 | |||
384 | return result; | ||
385 | }, | ||
386 | |||
387 | //------------------------------------------------------------------------- | ||
388 | |||
389 | 'unpackData': function (someData) { | ||
390 | var result; | ||
391 | |||
392 | result = Clipperz.PM.DataModel.Record.superclass.unpackData.apply(this, arguments); | ||
393 | |||
394 | if (MochiKit.Base.isUndefinedOrNull(result['notes'])) { | ||
395 | result['notes'] = '' | ||
396 | } | ||
397 | |||
398 | return result; | ||
399 | }, | ||
400 | |||
401 | //------------------------------------------------------------------------- | ||
402 | |||
403 | 'prepareRemoteDataWithKey': function (aKey) { | ||
404 | var deferredResult; | ||
405 | varnewVersionKey; | ||
406 | var result; | ||
407 | |||
408 | newVersionKey = Clipperz.PM.Crypto.randomKey(); | ||
409 | result = {}; | ||
410 | |||
411 | deferredResult = new Clipperz.Async.Deferred("Record.prepareRemoteDataWithKey", {trace:false}); | ||
412 | deferredResult.addCallbackList([ | ||
413 | Clipperz.Async.collectResults("Record.prepareRemoteDataWithKey - collect results", { | ||
414 | 'isBrandNew': MochiKit.Base.method(this, 'isBrandNew'), | ||
415 | 'versionHasPendingChanges':[ | ||
416 | // MochiKit.Base.method(this, 'getCurrentRecordVersion'), | ||
417 | // MochiKit.Base.methodcaller('hasPendingChanges') | ||
418 | MochiKit.Base.method(this, 'invokeCurrentRecordVersionMethod', 'hasPendingChanges') | ||
419 | ] | ||
420 | }), | ||
421 | Clipperz.Async.or, | ||
422 | |||
423 | Clipperz.Async.deferredIf("Current Version has pending changes", [ | ||
424 | MochiKit.Base.method(this, 'createNewRecordVersion'), | ||
425 | MochiKit.Base.methodcaller('prepareRemoteDataWithKey', newVersionKey), | ||
426 | MochiKit.Base.partial(Clipperz.Async.setItem, result, 'currentRecordVersion'), | ||
427 | MochiKit.Base.method(this, 'setCurrentRecordVersionKey', newVersionKey) | ||
428 | ], []), | ||
429 | |||
430 | MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.prepareRemoteDataWithKey, this, aKey), | ||
431 | MochiKit.Base.partial(Clipperz.Async.setItem, result, 'record'), | ||
432 | |||
433 | MochiKit.Base.partial(MochiKit.Async.succeed, result) | ||
434 | ]); | ||
435 | |||
436 | deferredResult.callback(); | ||
437 | |||
438 | return deferredResult; | ||
439 | }, | ||
440 | |||
441 | //========================================================================= | ||
442 | |||
443 | 'fields': function () { | ||
444 | return this.invokeCurrentRecordVersionMethod('fields'); | ||
445 | }, | ||
446 | |||
447 | 'addField': function (someParameters) { | ||
448 | return this.invokeCurrentRecordVersionMethod('addField', someParameters); | ||
449 | }, | ||
450 | |||
451 | 'removeField': function (someParameters) { | ||
452 | return this.invokeCurrentRecordVersionMethod('removeField', someParameters); | ||
453 | }, | ||
454 | |||
455 | //'sortFieldReference': function (someSortedFieldReferences) { | ||
456 | // return this.invokeCurrentRecordVersionMethod('sortFieldReference', someSortedFieldReferences); | ||
457 | //}, | ||
458 | |||
459 | 'getFieldsValues': function () { | ||
460 | return this.invokeCurrentRecordVersionMethod('getFieldsValues'); | ||
461 | }, | ||
462 | |||
463 | 'fieldWithLabel': function (aLabel) { | ||
464 | return Clipperz.Async.callbacks("Record.fieldWithLabel", [ | ||
465 | MochiKit.Base.method(this, 'fields'), | ||
466 | MochiKit.Base.values, | ||
467 | MochiKit.Base.partial(Clipperz.Async.deferredFilter, function (aField) { | ||
468 | return Clipperz.Async.callbacks("Record.fieldWithLabel - check field label", [ | ||
469 | MochiKit.Base.methodcaller('label'), | ||
470 | MochiKit.Base.partial(MochiKit.Base.operator.eq, aLabel) | ||
471 | ], {trace:false}, aField); | ||
472 | }), | ||
473 | function (someFilteredResults) { | ||
474 | var result; | ||
475 | |||
476 | switch (someFilteredResults.length) { | ||
477 | case 0: | ||
478 | result = null; | ||
479 | break; | ||
480 | case 1: | ||
481 | result = someFilteredResults[0]; | ||
482 | break; | ||
483 | default: | ||
484 | WTF = TODO; | ||
485 | break; | ||
486 | } | ||
487 | |||
488 | return result; | ||
489 | } | ||
490 | ], {trace:false}); | ||
491 | }, | ||
492 | |||
493 | //========================================================================= | ||
494 | |||
495 | 'getVersion': function (aVersionReference) { | ||
496 | return Clipperz.Async.callbacks("Record.getVersion", [ | ||
497 | MochiKit.Base.method(this, 'getVersions'), | ||
498 | MochiKit.Base.itemgetter(aVersionReference) | ||
499 | ], {trace:false}); | ||
500 | }, | ||
501 | |||
502 | //------------------------------------------------------------------------- | ||
503 | |||
504 | 'getVersionKey': function (aVersionReference) { | ||
505 | vardeferredResult; | ||
506 | var transientStateKey; | ||
507 | |||
508 | transientStateKey = 'versionKeys' + '.' + aVersionReference; | ||
509 | if (this.transientState().getValue(transientStateKey) != null) { | ||
510 | deferredResult = MochiKit.Async.succeed(this.transientState().getValue(transientStateKey)); | ||
511 | } else { | ||
512 | deferredResult = Clipperz.Async.callbacks("Record.getVersionKey", [ | ||
513 | MochiKit.Base.method(this, 'getVersions'), | ||
514 | MochiKit.Base.partial(MochiKit.Base.operator.eq, aVersionReference, this.currentVersionReference()), | ||
515 | Clipperz.Async.deferredIf("getVersionKey for current version", [ | ||
516 | MochiKit.Base.method(this, 'getCurrentRecordVersionKey'), | ||
517 | MochiKit.Base.method(this.transientState(), 'setValue', transientStateKey) | ||
518 | ],[ | ||
519 | MochiKit.Async.fail | ||
520 | ]) | ||
521 | ], {trace:false}); | ||
522 | } | ||
523 | |||
524 | return deferredResult; | ||
525 | }, | ||
526 | |||
527 | //------------------------------------------------------------------------- | ||
528 | |||
529 | 'versions': function () { | ||
530 | return this._versions; | ||
531 | }, | ||
532 | |||
533 | 'getVersions': function () { | ||
534 | return Clipperz.Async.callbacks("Record.versions", [ | ||
535 | MochiKit.Base.method(this, 'getValue', 'fakeKey, just to trigger unpackRemoteData'), | ||
536 | MochiKit.Base.bind(function () { return this._versions; }, this) | ||
537 | ], {trace:false}); | ||
538 | }, | ||
539 | |||
540 | //------------------------------------------------------------------------- | ||
541 | |||
542 | 'getCurrentRecordVersion': function () { | ||
543 | return Clipperz.Async.callbacks("Record.getCurrentRecordVersion", [ | ||
544 | // MochiKit.Base.method(this, 'getValue', 'fakeKey, just to trigger unpackRemoteData'), | ||
545 | // MochiKit.Base.bind(function () { return this._currentRecordVersion; }, this) | ||
546 | |||
547 | MochiKit.Base.method(this, 'versions'), | ||
548 | MochiKit.Base.itemgetter(this.currentVersionReference()), | ||
549 | Clipperz.Async.deferredIf("The current version is available", [ | ||
550 | MochiKit.Async.succeed | ||
551 | ], [ | ||
552 | MochiKit.Base.method(this, 'getVersions'), | ||
553 | MochiKit.Base.bind(function (someVersions) { return someVersions[this.currentVersionReference()]}, this) | ||
554 | ]) | ||
555 | ], {trace:false}); | ||
556 | }, | ||
557 | |||
558 | 'setCurrentRecordVersion': function (aRecordVersion) { | ||
559 | this._currentVersionReference = aRecordVersion.reference(); | ||
560 | }, | ||
561 | |||
562 | //......................................................................... | ||
563 | |||
564 | 'currentVersionReference': function () { | ||
565 | return this._currentVersionReference; | ||
566 | }, | ||
567 | |||
568 | //------------------------------------------------------------------------- | ||
569 | |||
570 | 'createNewRecordVersion': function () { | ||
571 | var deferredResult; | ||
572 | |||
573 | if (this.isBrandNew()) { | ||
574 | deferredResult = this.getCurrentRecordVersion(); | ||
575 | } else { | ||
576 | var newVersion; | ||
577 | |||
578 | newVersion = new Clipperz.PM.DataModel.Record.Version({ | ||
579 | // 'reference': versionKey, | ||
580 | 'retrieveKeyFunction':MochiKit.Base.method(this, 'getVersionKey'), | ||
581 | // 'remoteData': {}, | ||
582 | 'getVersion': MochiKit.Base.method(this, 'getVersion') | ||
583 | }) | ||
584 | this._versions[newVersion.reference()] = newVersion; | ||
585 | |||
586 | deferredResult = Clipperz.Async.callbacks("Record.createNewRecordVersion", [ | ||
587 | // MochiKit.Base.method(this, 'getCurrentRecordVersion'), | ||
588 | // MochiKit.Base.methodcaller('values'), | ||
589 | MochiKit.Base.method(this, 'invokeCurrentRecordVersionMethod', 'values'), | ||
590 | MochiKit.Base.method(newVersion, 'setValues'), | ||
591 | |||
592 | Clipperz.Async.collectResults("Record.createNewRecordVersion [collect results]", { | ||
593 | 'reference':MochiKit.Base.method(this, 'currentVersionReference'), | ||
594 | 'key': MochiKit.Base.method(this, 'getCurrentRecordVersionKey') | ||
595 | }, {trace:false}), | ||
596 | MochiKit.Base.method(newVersion, 'setPreviousVersionReferenceAndKey'), | ||
597 | |||
598 | // MochiKit.Base.method(this, 'getCurrentRecordVersion'), | ||
599 | // MochiKit.Base.method(this, 'revertChanges'), | ||
600 | MochiKit.Base.method(this, 'invokeCurrentRecordVersionMethod', 'revertChanges'), | ||
601 | |||
602 | MochiKit.Base.method(this, 'setCurrentRecordVersion', newVersion), | ||
603 | MochiKit.Base.partial(MochiKit.Async.succeed, newVersion) | ||
604 | ], {trace:false}); | ||
605 | } | ||
606 | |||
607 | return deferredResult; | ||
608 | }, | ||
609 | |||
610 | //------------------------------------------------------------------------- | ||
611 | |||
612 | 'getCurrentRecordVersionKey': function () { | ||
613 | return Clipperz.Async.callbacks("Record.getCurrentRecordVersionKey", [ | ||
614 | MochiKit.Base.method(this, 'getValue', 'currentVersionKey'), | ||
615 | Clipperz.Async.deferredIf("currentVersionKey is NOT null", [ | ||
616 | MochiKit.Async.succeed | ||
617 | ], [ | ||
618 | MochiKit.Base.method(this, 'getKey') | ||
619 | ]) | ||
620 | ], {trace:false}); | ||
621 | }, | ||
622 | |||
623 | 'setCurrentRecordVersionKey': function (aValue) { | ||
624 | //TODO: triple check this method! | ||
625 | return Clipperz.Async.callbacks("Record.setCurrentRecordVersionKey", [ | ||
626 | MochiKit.Base.method(this, 'setValue', 'currentVersionKey', aValue) | ||
627 | ], {trace:false}); | ||
628 | }, | ||
629 | |||
630 | //------------------------------------------------------------------------- | ||
631 | |||
632 | 'invokeCurrentRecordVersionMethod': function (aMethodName, someValues) { | ||
633 | return Clipperz.Async.callbacks("Record.invokeCurrentRecordVersionMethod", [ | ||
634 | MochiKit.Base.method(this, 'getCurrentRecordVersion'), | ||
635 | MochiKit.Base.methodcaller(aMethodName, someValues) | ||
636 | ], {trace:false}); | ||
637 | }, | ||
638 | |||
639 | |||
640 | 'lazilyinvokeCurrentRecordVersionMethod': function (aMethodName, someValues, defaultResult) { | ||
641 | return Clipperz.Async.callbacks("Record.lazilyinvokeCurrentRecordVersionMethod", [ | ||
642 | MochiKit.Base.method(this, 'currentVersionReference'), | ||
643 | Clipperz.Async.deferredIf("versions has been loaded", [ | ||
644 | MochiKit.Base.method(this, 'getCurrentRecordVersion'), | ||
645 | MochiKit.Base.methodcaller(aMethodName, someValues), | ||
646 | ], [ | ||
647 | MochiKit.Base.partial(MochiKit.Async.succeed, defaultResult), | ||
648 | ]) | ||
649 | ], {trace:false}); | ||
650 | }, | ||
651 | |||
652 | //========================================================================= | ||
653 | |||
654 | 'hasPendingChanges': function () { | ||
655 | var deferredResult; | ||
656 | |||
657 | if (this.hasInitiatedObjectDataStore()) { | ||
658 | deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.Record.hasPendingChanges", {trace:false}); | ||
659 | deferredResult.collectResults({ | ||
660 | 'super': MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.hasPendingChanges, this), | ||
661 | 'currentVersion': [ | ||
662 | // MochiKit.Base.method(this, 'getCurrentRecordVersion'), | ||
663 | // MochiKit.Base.methodcaller('hasPendingChanges') | ||
664 | MochiKit.Base.method(this, 'invokeCurrentRecordVersionMethod', 'hasPendingChanges') | ||
665 | ], | ||
666 | 'directLogins': [ | ||
667 | MochiKit.Base.method(this, 'directLogins'), | ||
668 | MochiKit.Base.values, | ||
669 | MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('hasPendingChanges')), | ||
670 | Clipperz.Async.collectAll, | ||
671 | Clipperz.Async.or | ||
672 | // function(someValues) { | ||
673 | // return MochiKit.Iter.some(someValues, MochiKit.Base.operator.identity); | ||
674 | // } | ||
675 | ] | ||
676 | }); | ||
677 | deferredResult.addCallback(MochiKit.Base.values); | ||
678 | deferredResult.addCallback(MochiKit.Base.bind(function(someValues) { | ||
679 | var result; | ||
680 | result = MochiKit.Iter.some(someValues, MochiKit.Base.operator.identity); | ||
681 | |||
682 | if ((result == false) && (this.isBrandNew() == false)) { | ||
683 | result = MochiKit.Iter.some(MochiKit.Base.values(this.transientState().getValue('hasPendingChanges.indexData')), MochiKit.Base.operator.identity); | ||
684 | } | ||
685 | |||
686 | return result; | ||
687 | }, this)); | ||
688 | |||
689 | deferredResult.callback(); | ||
690 | } else { | ||
691 | deferredResult = Clipperz.Async.callbacks("Recrod.hasPendingChanges [hasInitiatedObjectDataStore == false]", [ | ||
692 | MochiKit.Base.method(this, 'directLogins'), | ||
693 | MochiKit.Base.values, | ||
694 | MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('hasPendingChanges')), | ||
695 | Clipperz.Async.collectAll, | ||
696 | Clipperz.Async.or | ||
697 | // function(someValues) { | ||
698 | // return MochiKit.Iter.some(someValues, MochiKit.Base.operator.identity); | ||
699 | // } | ||
700 | ], {trace:false}) | ||
701 | } | ||
702 | |||
703 | return deferredResult; | ||
704 | }, | ||
705 | |||
706 | //------------------------------------------------------------------------- | ||
707 | |||
708 | 'hasPendingChangesWhenBrandNew': function () { | ||
709 | var deferredResult; | ||
710 | |||
711 | deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.Record.hasPendingChangesWhenBrandNew", {trace:false}); | ||
712 | deferredResult.collectResults({ | ||
713 | 'label': [ | ||
714 | MochiKit.Base.method(this, 'label'), | ||
715 | MochiKit.Base.partial(MochiKit.Base.operator.ne, '') | ||
716 | ], | ||
717 | 'notes': [ | ||
718 | MochiKit.Base.method(this, 'notes'), | ||
719 | MochiKit.Base.partial(MochiKit.Base.operator.ne, '') | ||
720 | ] | ||
721 | }); | ||
722 | // deferredResult.addCallback(MochiKit.Base.values); | ||
723 | // deferredResult.addCallback(function(someValues) { | ||
724 | // return MochiKit.Iter.some(someValues, MochiKit.Base.operator.identity); | ||
725 | // }); | ||
726 | deferredResult.addCallback(Clipperz.Async.or); | ||
727 | |||
728 | deferredResult.callback(); | ||
729 | |||
730 | return deferredResult; | ||
731 | }, | ||
732 | |||
733 | //------------------------------------------------------------------------- | ||
734 | |||
735 | 'isBrandNewWithNoPendingChanges': function () { | ||
736 | vardeferredResult; | ||
737 | |||
738 | if (this.isBrandNew() == false) { | ||
739 | deferredResult = MochiKit.Async.succeed(false); | ||
740 | } else { | ||
741 | deferredResult = Clipperz.Async.callbacks("Record.isBrandNewWithNoPendingChanges", [ | ||
742 | MochiKit.Base.method(this, 'hasPendingChanges'), | ||
743 | MochiKit.Base.operator.lognot | ||
744 | ], {trace:false}); | ||
745 | } | ||
746 | |||
747 | return deferredResult; | ||
748 | }, | ||
749 | |||
750 | //========================================================================= | ||
751 | |||
752 | 'revertChanges': function () { | ||
753 | var deferredResult; | ||
754 | |||
755 | if (this.isBrandNew() == false) { | ||
756 | deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.Record.revertChanges", {trace:false}); | ||
757 | deferredResult.addMethod(this, 'hasPendingChanges'); | ||
758 | deferredResult.addIf([ | ||
759 | // MochiKit.Base.method(this, 'getCurrentRecordVersion'), | ||
760 | // MochiKit.Base.methodcaller('revertChanges'), | ||
761 | MochiKit.Base.method(this,'invokeCurrentRecordVersionMethod', 'revertChanges'), | ||
762 | |||
763 | MochiKit.Base.method(this, 'directLogins'), | ||
764 | MochiKit.Base.values, | ||
765 | MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('revertChanges')), | ||
766 | |||
767 | MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.revertChanges, this) | ||
768 | ], [ | ||
769 | MochiKit.Async.succeed | ||
770 | ]); | ||
771 | deferredResult.callback(); | ||
772 | } else { | ||
773 | // this.deleteAllCleanTextData(); | ||
774 | deferredResult = MochiKit.Async.succeed(); | ||
775 | } | ||
776 | |||
777 | return deferredResult; | ||
778 | }, | ||
779 | |||
780 | //------------------------------------------------------------------------- | ||
781 | |||
782 | 'resetTransientState': function (isCommitting) { | ||
783 | // if ((isCommitting == false) && (this.transientState().getValue('directLogins') != null)) { | ||
784 | // this._directLogins = this.transientState().getValue('directLogins'); | ||
785 | // } | ||
786 | |||
787 | return Clipperz.Async.callbacks("Record.resetTransientState", [ | ||
788 | //- MochiKit.Base.method(this, 'getCurrentRecordVersion'), | ||
789 | //- MochiKit.Base.methodcaller('resetTransientState'), | ||
790 | // MochiKit.Base.method(this, 'invokeCurrentRecordVersionMethod', 'resetTransientState'), | ||
791 | MochiKit.Base.method(this, 'lazilyinvokeCurrentRecordVersionMethod', 'resetTransientState'), | ||
792 | |||
793 | MochiKit.Base.method(this, 'directLogins'), | ||
794 | MochiKit.Base.values, | ||
795 | MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('resetTransientState')), | ||
796 | |||
797 | MochiKit.Base.bind(function () { | ||
798 | if ((isCommitting == false) && (this.transientState().getValue('directLogins') != null)) { | ||
799 | this._directLogins = this.transientState().getValue('directLogins'); | ||
800 | } | ||
801 | }, this), | ||
802 | |||
803 | MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.resetTransientState, this, isCommitting) | ||
804 | ], {trace:false}) | ||
805 | }, | ||
806 | |||
807 | //------------------------------------------------------------------------- | ||
808 | |||
809 | 'commitTransientState': function () { | ||
810 | var deferredResult; | ||
811 | |||
812 | deferredResult = new Clipperz.Async.Deferred("Clipperz.PM.DataModel.Record.commitTransientState", {trace:false}); | ||
813 | deferredResult.addMethod(this, 'hasPendingChanges'); | ||
814 | deferredResult.addIf([ | ||
815 | MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.commitTransientState, this), | ||
816 | // MochiKit.Base.method(this, 'getCurrentRecordVersion'), | ||
817 | // MochiKit.Base.methodcaller('commitTransientState'), | ||
818 | MochiKit.Base.method(this, 'invokeCurrentRecordVersionMethod', 'commitTransientState'), | ||
819 | MochiKit.Base.method(this, 'directLogins'), | ||
820 | MochiKit.Base.values, | ||
821 | MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('commitTransientState')) | ||
822 | ], [ | ||
823 | MochiKit.Async.succeed | ||
824 | ]); | ||
825 | deferredResult.callback(); | ||
826 | |||
827 | return deferredResult; | ||
828 | }, | ||
829 | |||
830 | //========================================================================= | ||
831 | |||
832 | 'retrieveDirectLoginIndexDataFunction': function () { | ||
833 | return this._retrieveDirectLoginIndexDataFunction; | ||
834 | }, | ||
835 | |||
836 | 'setDirectLoginIndexDataFunction': function () { | ||
837 | return this._setDirectLoginIndexDataFunction; | ||
838 | }, | ||
839 | |||
840 | 'removeDirectLoginIndexDataFunction': function () { | ||
841 | return this._removeDirectLoginIndexDataFunction; | ||
842 | }, | ||
843 | |||
844 | //========================================================================= | ||
845 | |||
846 | 'deleteAllCleanTextData': function () { | ||
847 | // return Clipperz.PM.DataModel.Record.superclass.deleteAllCleanTextData.apply(this, arguments); | ||
848 | |||
849 | return Clipperz.Async.callbacks("Record.deleteAllCleanTextData", [ | ||
850 | MochiKit.Base.method(this, 'versions'), | ||
851 | MochiKit.Base.values, | ||
852 | MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('deleteAllCleanTextData')), | ||
853 | |||
854 | MochiKit.Base.method(this, 'directLogins'), | ||
855 | MochiKit.Base.values, | ||
856 | MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('deleteAllCleanTextData')), | ||
857 | |||
858 | MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.deleteAllCleanTextData, this) | ||
859 | ], {trace:false}); | ||
860 | }, | ||
861 | |||
862 | 'hasAnyCleanTextData': function () { | ||
863 | // return Clipperz.PM.DataModel.Record.superclass.hasAnyCleanTextData.apply(this, arguments); | ||
864 | |||
865 | return Clipperz.Async.callbacks("Record.hasAnyCleanTextData", [ | ||
866 | Clipperz.Async.collectResults("Record.hasAnyCleanTextData [collect results]", { | ||
867 | 'versions':[ | ||
868 | MochiKit.Base.method(this, 'versions'), | ||
869 | MochiKit.Base.values, | ||
870 | MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('hasAnyCleanTextData')), | ||
871 | Clipperz.Async.collectAll | ||
872 | ], | ||
873 | 'directLogins': [ | ||
874 | MochiKit.Base.method(this, 'directLogins'), | ||
875 | MochiKit.Base.values, | ||
876 | MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('hasAnyCleanTextData')), | ||
877 | Clipperz.Async.collectAll | ||
878 | ], | ||
879 | 'super': [ | ||
880 | MochiKit.Base.bind(Clipperz.PM.DataModel.Record.superclass.hasAnyCleanTextData, this) | ||
881 | ] | ||
882 | }, {trace:false}), | ||
883 | Clipperz.Async.or | ||
884 | ]) | ||
885 | }, | ||
886 | |||
887 | //========================================================================= | ||
888 | __syntaxFix__: "syntax fix" | ||
889 | }); | ||
890 | |||
891 | |||
diff --git a/frontend/delta/js/Clipperz/PM/DataModel/User.Header.Legacy.js b/frontend/delta/js/Clipperz/PM/DataModel/User.Header.Legacy.js new file mode 100644 index 0000000..cda5a41 --- a/dev/null +++ b/frontend/delta/js/Clipperz/PM/DataModel/User.Header.Legacy.js | |||
@@ -0,0 +1,182 @@ | |||
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 | try { if (typeof(Clipperz.PM.DataModel.User) == 'undefined') { throw ""; }} catch (e) { | ||
25 | throw "Clipperz.PM.DataModel.User.Header.Legacy depends on Clipperz.PM.DataModel.User!"; | ||
26 | } | ||
27 | |||
28 | if (typeof(Clipperz.PM.DataModel.User.Header) == 'undefined') { Clipperz.PM.DataModel.User.Header = {}; } | ||
29 | |||
30 | Clipperz.PM.DataModel.User.Header.Legacy = function(args) { | ||
31 | //args = args || {}; | ||
32 | Clipperz.PM.DataModel.User.Header.Legacy.superclass.constructor.apply(this, arguments); | ||
33 | |||
34 | this._retrieveRecordDetailFunction = args.retrieveRecordDetailFunction|| Clipperz.Base.exception.raise('MandatoryParameter'); | ||
35 | this._records = null; | ||
36 | //this._directLogins = null; | ||
37 | |||
38 | return this; | ||
39 | } | ||
40 | |||
41 | |||
42 | Clipperz.Base.extend(Clipperz.PM.DataModel.User.Header.Legacy, Clipperz.PM.DataModel.EncryptedRemoteObject, { | ||
43 | |||
44 | 'toString': function() { | ||
45 | return "Clipperz.PM.DataModel.User.Header.Legacy"; | ||
46 | }, | ||
47 | |||
48 | //------------------------------------------------------------------------- | ||
49 | |||
50 | 'retrieveRecordDetailFunction': function () { | ||
51 | return this._retrieveRecordDetailFunction; | ||
52 | }, | ||
53 | |||
54 | //------------------------------------------------------------------------- | ||
55 | |||
56 | 'getRecordKey': function (aRecordReference) { | ||
57 | var deferredResult; | ||
58 | |||
59 | deferredResult = new Clipperz.Async.Deferred("User.Header.Legacy.getRecordKey", {trace:false}); | ||
60 | deferredResult.addMethod(this, 'getRecordIndexData'); | ||
61 | deferredResult.addCallback(MochiKit.Base.itemgetter('key')) | ||
62 | deferredResult.callback(); | ||
63 | |||
64 | return deferredResult; | ||
65 | }, | ||
66 | |||
67 | //========================================================================= | ||
68 | |||
69 | 'getRecordIndexData': function (aRecordReference) { | ||
70 | return this.getValue('records.' + aRecordReference); | ||
71 | }, | ||
72 | |||
73 | 'updateRecordIndexData': function (aRecordReference, aKey, aValue) { | ||
74 | return this.setValue('records.' + aRecordReference + "." + aKey, aValue); | ||
75 | }, | ||
76 | |||
77 | //------------------------------------------------------------------------- | ||
78 | |||
79 | 'getDirectLoginIndexData': function (aDirectLoginReference) { | ||
80 | return this.getValue('directLogins.' + aDirectLoginReference); | ||
81 | }, | ||
82 | |||
83 | 'setDirectLoginIndexData': function (aDirectLoginReference, aKey, aValue) { | ||
84 | return this.setValue('directLogins.' + aDirectLoginReference + '.' + aKey, aValue); | ||
85 | }, | ||
86 | |||
87 | 'removeDirectLoginIndexData': function (aDirectLoginReference) { | ||
88 | return this.removeValue('directLogins.' + aDirectLoginReference); | ||
89 | }, | ||
90 | |||
91 | //========================================================================= | ||
92 | |||
93 | 'records': function () { | ||
94 | vardeferredResult; | ||
95 | var deferredLock; | ||
96 | |||
97 | deferredLock = this.getDeferredLockForKey('records'); | ||
98 | |||
99 | deferredResult = new Clipperz.Async.Deferred("User.Header.Legacy.records", {trace:false}); | ||
100 | deferredResult.acquireLock(deferredLock); | ||
101 | deferredResult.addCallback(MochiKit.Base.bind(function () { | ||
102 | var innerDeferredResult; | ||
103 | |||
104 | if (this._records == null) { | ||
105 | innerDeferredResult = new Clipperz.Async.Deferred("User.Header.Legacy.records <inner deferred>", {trace:false}); | ||
106 | innerDeferredResult.collectResults({ | ||
107 | 'header': [ | ||
108 | // MochiKit.Base.method(this, 'getObjectDataStore'), | ||
109 | // MochiKit.Base.methodcaller('values') | ||
110 | MochiKit.Base.method(this, 'values') | ||
111 | ], | ||
112 | 'recordsStats': [ | ||
113 | MochiKit.Base.method(this, 'getRemoteData'), | ||
114 | MochiKit.Base.itemgetter('recordsStats') | ||
115 | ] | ||
116 | }); | ||
117 | innerDeferredResult.addCallback(MochiKit.Base.bind(function (someObjectData) { | ||
118 | var reference; | ||
119 | |||
120 | this._records = {}; | ||
121 | // this._directLogins = {}; | ||
122 | |||
123 | for (reference in someObjectData['header']['records']) { | ||
124 | varrecord; | ||
125 | |||
126 | record = new Clipperz.PM.DataModel.Record({ | ||
127 | 'reference': reference, | ||
128 | 'retrieveKeyFunction': MochiKit.Base.method(this, 'getRecordKey'), | ||
129 | 'retrieveRemoteDataFunction':this.retrieveRecordDetailFunction(), | ||
130 | // 'encryptedDataKeypath': 'data', | ||
131 | // 'encryptedVersionKeypath': 'version', | ||
132 | |||
133 | 'retrieveIndexDataFunction':MochiKit.Base.method(this, 'getRecordIndexData'), | ||
134 | 'updateIndexDataFunction': MochiKit.Base.method(this, 'updateRecordIndexData'), | ||
135 | 'updateDate': someObjectData['recordsStats'][reference]['updateDate'], | ||
136 | |||
137 | 'retrieveDirectLoginIndexDataFunction':MochiKit.Base.method(this, 'getDirectLoginIndexData'), | ||
138 | 'setDirectLoginIndexDataFunction': MochiKit.Base.method(this, 'setDirectLoginIndexData'), | ||
139 | 'removeDirectLoginIndexDataFunction':MochiKit.Base.method(this, 'removeDirectLoginIndexData') | ||
140 | }); | ||
141 | |||
142 | this._records[reference] = record; | ||
143 | } | ||
144 | |||
145 | for (reference in someObjectData['header']['directLogins']) { | ||
146 | vardirectLogin; | ||
147 | var record; | ||
148 | |||
149 | record = this._records[someObjectData['header']['directLogins'][reference]['record']]; | ||
150 | if (record != null) { | ||
151 | directLogin = new Clipperz.PM.DataModel.DirectLogin({ | ||
152 | 'reference': reference, | ||
153 | 'record': record//, | ||
154 | // 'retrieveIndexDataFunction':MochiKit.Base.method(this, 'getDirectLoginIndexData'), | ||
155 | // 'setIndexDataFunction': MochiKit.Base.method(this, 'setDirectLoginIndexData'), | ||
156 | // 'removeIndexDataFunction': MochiKit.Base.method(this, 'removeDirectLoginIndexData') | ||
157 | }); | ||
158 | } else { | ||
159 | Clipperz.log("WARNING: DIRECT LOGIN without a matching RECORD!!"); | ||
160 | } | ||
161 | } | ||
162 | |||
163 | return this._records; | ||
164 | }, this)); | ||
165 | innerDeferredResult.callback(); | ||
166 | } else { | ||
167 | innerDeferredResult = MochiKit.Async.succeed(this._records); | ||
168 | } | ||
169 | |||
170 | return innerDeferredResult; | ||
171 | }, this)); | ||
172 | deferredResult.releaseLock(deferredLock); | ||
173 | deferredResult.callback(); | ||
174 | |||
175 | return deferredResult; | ||
176 | }, | ||
177 | |||
178 | //========================================================================= | ||
179 | __syntaxFix__: "syntax fix" | ||
180 | }); | ||
181 | |||
182 | |||
diff --git a/frontend/delta/js/Clipperz/PM/DataModel/User.Header.OneTimePasswords.js b/frontend/delta/js/Clipperz/PM/DataModel/User.Header.OneTimePasswords.js new file mode 100644 index 0000000..e82da47 --- a/dev/null +++ b/frontend/delta/js/Clipperz/PM/DataModel/User.Header.OneTimePasswords.js | |||
@@ -0,0 +1,117 @@ | |||
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 | try { if (typeof(Clipperz.PM.DataModel.User) == 'undefined') { throw ""; }} catch (e) { | ||
25 | throw "Clipperz.PM.DataModel.User.Header.OneTimePasswords depends on Clipperz.PM.DataModel.User!"; | ||
26 | } | ||
27 | if (typeof(Clipperz.PM.DataModel.User.Header) == 'undefined') { Clipperz.PM.DataModel.User.Header = {}; } | ||
28 | |||
29 | //----------------------------------------------------------------------------- | ||
30 | |||
31 | Clipperz.PM.DataModel.User.Header.OneTimePasswords = function(args) { | ||
32 | Clipperz.PM.DataModel.User.Header.OneTimePasswords.superclass.constructor.apply(this, arguments); | ||
33 | |||
34 | this._oneTimePasswords = null; | ||
35 | |||
36 | return this; | ||
37 | } | ||
38 | |||
39 | //----------------------------------------------------------------------------- | ||
40 | |||
41 | Clipperz.Base.extend(Clipperz.PM.DataModel.User.Header.OneTimePasswords, Clipperz.PM.DataModel.EncryptedRemoteObject, { | ||
42 | |||
43 | 'toString': function() { | ||
44 | return "Clipperz.PM.DataModel.User.Header.OneTimePasswords"; | ||
45 | }, | ||
46 | |||
47 | //------------------------------------------------------------------------- | ||
48 | /* | ||
49 | 'packData': function (someData) { //++ | ||
50 | var result; | ||
51 | |||
52 | result = Clipperz.PM.DataModel.User.Header.OneTimePasswords.superclass.packData.apply(this, arguments); | ||
53 | |||
54 | return result; | ||
55 | }, | ||
56 | */ | ||
57 | //------------------------------------------------------------------------- | ||
58 | /* | ||
59 | 'packRemoteData': function (someData) { | ||
60 | var result; | ||
61 | |||
62 | result = Clipperz.PM.DataModel.User.Header.OneTimePasswords.superclass.packRemoteData.apply(this, arguments); | ||
63 | |||
64 | return result; | ||
65 | }, | ||
66 | */ | ||
67 | //------------------------------------------------------------------------- | ||
68 | /* | ||
69 | 'prepareRemoteDataWithKey': function (aKey) { | ||
70 | var result; | ||
71 | |||
72 | result = Clipperz.PM.DataModel.User.Header.OneTimePasswords.superclass.prepareRemoteDataWithKey.apply(this, arguments); | ||
73 | |||
74 | return result; | ||
75 | }, | ||
76 | */ | ||
77 | //========================================================================= | ||
78 | |||
79 | 'oneTimePasswords': function () { | ||
80 | vardeferredResult; | ||
81 | |||
82 | deferredResult = new Clipperz.Async.Deferred("User.Header.OneTimePasswords.oneTimePasswords", {trace:false}); | ||
83 | if (this._oneTimePasswords == null) { | ||
84 | deferredResult.addMethod(this, 'values') | ||
85 | deferredResult.addCallback(MochiKit.Base.bind(function (someData) { | ||
86 | varotpKey; | ||
87 | |||
88 | this._oneTimePasswords = {}; | ||
89 | |||
90 | for (otpKey in someData) { | ||
91 | var otp; | ||
92 | var otpParameters; | ||
93 | |||
94 | otpParameters = Clipperz.Base.deepClone(someData[otpKey]); | ||
95 | otpParameters['reference'] = otpKey; | ||
96 | |||
97 | otp = new Clipperz.PM.DataModel.OneTimePassword(otpParameters); | ||
98 | this._oneTimePasswords[otpKey] = otp; | ||
99 | } | ||
100 | |||
101 | return this._oneTimePasswords; | ||
102 | |||
103 | }, this)); | ||
104 | deferredResult.callback(); | ||
105 | } else { | ||
106 | deferredResult = MochiKit.Async.succeed(this._oneTimePasswords); | ||
107 | } | ||
108 | |||
109 | return deferredResult; | ||
110 | }, | ||
111 | |||
112 | //========================================================================= | ||
113 | __syntaxFix__: "syntax fix" | ||
114 | }); | ||
115 | |||
116 | //----------------------------------------------------------------------------- | ||
117 | |||
diff --git a/frontend/delta/js/Clipperz/PM/DataModel/User.Header.Preferences.js b/frontend/delta/js/Clipperz/PM/DataModel/User.Header.Preferences.js new file mode 100644 index 0000000..f1f95e8 --- a/dev/null +++ b/frontend/delta/js/Clipperz/PM/DataModel/User.Header.Preferences.js | |||
@@ -0,0 +1,48 @@ | |||
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 | try { if (typeof(Clipperz.PM.DataModel.User) == 'undefined') { throw ""; }} catch (e) { | ||
25 | throw "Clipperz.PM.DataModel.User.Header.Preferences depends on Clipperz.PM.DataModel.User!"; | ||
26 | } | ||
27 | |||
28 | if (typeof(Clipperz.PM.DataModel.User.Header) == 'undefined') { Clipperz.PM.DataModel.User.Header = {}; } | ||
29 | |||
30 | Clipperz.PM.DataModel.User.Header.Preferences = function(args) { | ||
31 | Clipperz.PM.DataModel.User.Header.Preferences.superclass.constructor.apply(this, arguments); | ||
32 | |||
33 | return this; | ||
34 | } | ||
35 | |||
36 | |||
37 | Clipperz.Base.extend(Clipperz.PM.DataModel.User.Header.Preferences, Clipperz.PM.DataModel.EncryptedRemoteObject, { | ||
38 | |||
39 | 'toString': function() { | ||
40 | return "Clipperz.PM.DataModel.User.Header.Preferences"; | ||
41 | }, | ||
42 | |||
43 | //------------------------------------------------------------------------- | ||
44 | //========================================================================= | ||
45 | __syntaxFix__: "syntax fix" | ||
46 | }); | ||
47 | |||
48 | |||
diff --git a/frontend/delta/js/Clipperz/PM/DataModel/User.Header.RecordIndex.js b/frontend/delta/js/Clipperz/PM/DataModel/User.Header.RecordIndex.js new file mode 100644 index 0000000..5681f70 --- a/dev/null +++ b/frontend/delta/js/Clipperz/PM/DataModel/User.Header.RecordIndex.js | |||
@@ -0,0 +1,685 @@ | |||
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 | try { if (typeof(Clipperz.PM.DataModel.User) == 'undefined') { throw ""; }} catch (e) { | ||
25 | throw "Clipperz.PM.DataModel.User.Header.RecordIndex depends on Clipperz.PM.DataModel.User!"; | ||
26 | } | ||
27 | |||
28 | if (typeof(Clipperz.PM.DataModel.User.Header) == 'undefined') { Clipperz.PM.DataModel.User.Header = {}; } | ||
29 | |||
30 | Clipperz.PM.DataModel.User.Header.RecordIndex = function(args) { | ||
31 | Clipperz.PM.DataModel.User.Header.RecordIndex.superclass.constructor.apply(this, arguments); | ||
32 | |||
33 | this._recordsData = new Clipperz.PM.DataModel.EncryptedRemoteObject({ | ||
34 | 'name':'recordsData', | ||
35 | 'retrieveKeyFunction': args.retrieveKeyFunction, | ||
36 | 'remoteData': { | ||
37 | 'data': args.recordsData['data'], | ||
38 | 'version': args.encryptedDataVersion, | ||
39 | 'recordsStats': args.recordsStats | ||
40 | }//, | ||
41 | // 'encryptedDataKeypath': 'data', | ||
42 | // 'encryptedVersionKeypath': 'version' | ||
43 | }); | ||
44 | |||
45 | this._directLoginsData = new Clipperz.PM.DataModel.EncryptedRemoteObject({ | ||
46 | 'name':'directLoginsData', | ||
47 | 'retrieveKeyFunction': args.retrieveKeyFunction, | ||
48 | 'remoteData': { | ||
49 | 'data': args.directLoginsData['data'], | ||
50 | 'version': args.encryptedDataVersion | ||
51 | }//, | ||
52 | // 'encryptedDataKeypath': 'data', | ||
53 | // 'encryptedVersionKeypath': 'version' | ||
54 | }); | ||
55 | |||
56 | this._lock = new MochiKit.Async.DeferredLock(); | ||
57 | this._transientState = null; | ||
58 | |||
59 | this._retrieveRecordDetailFunction = args.retrieveRecordDetailFunction|| Clipperz.Base.exception.raise('MandatoryParameter'); | ||
60 | this._recordsIndex = args.recordsData['index'] || Clipperz.Base.exception.raise('MandatoryParameter'); | ||
61 | this._directLoginsIndex = args.directLoginsData['index']|| Clipperz.Base.exception.raise('MandatoryParameter'); | ||
62 | |||
63 | this._records = null; | ||
64 | |||
65 | return this; | ||
66 | } | ||
67 | |||
68 | |||
69 | Clipperz.Base.extend(Clipperz.PM.DataModel.User.Header.RecordIndex, Object, { | ||
70 | |||
71 | 'toString': function() { | ||
72 | return "Clipperz.PM.DataModel.User.Header.RecordIndex"; | ||
73 | }, | ||
74 | |||
75 | //------------------------------------------------------------------------- | ||
76 | |||
77 | 'retrieveRecordDetailFunction': function () { | ||
78 | return this._retrieveRecordDetailFunction; | ||
79 | }, | ||
80 | |||
81 | //------------------------------------------------------------------------- | ||
82 | |||
83 | 'recordsIndex': function () { | ||
84 | return this._recordsIndex; | ||
85 | }, | ||
86 | |||
87 | 'recordsData': function () { | ||
88 | return this._recordsData; | ||
89 | }, | ||
90 | |||
91 | //------------------------------------------------------------------------- | ||
92 | |||
93 | 'directLoginsIndex': function () { | ||
94 | return this._directLoginsIndex; | ||
95 | }, | ||
96 | |||
97 | 'directLoginsData': function () { | ||
98 | return this._directLoginsData; | ||
99 | }, | ||
100 | |||
101 | //------------------------------------------------------------------------- | ||
102 | |||
103 | 'lock': function () { | ||
104 | return this._lock; | ||
105 | }, | ||
106 | |||
107 | //------------------------------------------------------------------------- | ||
108 | |||
109 | 'transientState': function () { | ||
110 | if (this._transientState == null) { | ||
111 | this._transientState = new Clipperz.KeyValueObjectStore(/*{'name':'User.Header.RecordIndex.transientState [1]'}*/); | ||
112 | } | ||
113 | |||
114 | return this._transientState; | ||
115 | }, | ||
116 | |||
117 | 'resetTransientState': function (isCommitting) { | ||
118 | if (this._transientState != null) { | ||
119 | this._transientState.removeAllData(); | ||
120 | } | ||
121 | |||
122 | this._transientState = null; | ||
123 | }, | ||
124 | |||
125 | //------------------------------------------------------------------------- | ||
126 | |||
127 | 'getRecordKey': function (aRecordReference) { | ||
128 | return Clipperz.Async.callbacks("User.Header.RecordIndex.getRecordKey", [ | ||
129 | MochiKit.Base.method(this, 'getRecordIndexData', aRecordReference), | ||
130 | MochiKit.Base.itemgetter('key') | ||
131 | ], {trace:false}); | ||
132 | }, | ||
133 | |||
134 | 'setRecordKey': function (aRecordReference, aValue) { | ||
135 | return this.updateRecordIndexData(aRecordReference, 'key', aValue); | ||
136 | }, | ||
137 | |||
138 | //------------------------------------------------------------------------- | ||
139 | |||
140 | 'getRecordIndexData': function (aRecordReference) { | ||
141 | return this.recordsData().getValue(this.recordsIndex()[aRecordReference]); | ||
142 | }, | ||
143 | |||
144 | //......................................................................... | ||
145 | |||
146 | 'updateRecordIndexData': function (aRecordReference, aKey, aValue) { | ||
147 | return this.recordsData().setValue(this.recordsIndex()[aRecordReference]+'.'+aKey, aValue); | ||
148 | }, | ||
149 | |||
150 | //------------------------------------------------------------------------- | ||
151 | |||
152 | 'getDirectLoginIndexData': function (aDirectLoginReference) { | ||
153 | return this.directLoginsData().getValue(this.directLoginsIndex()[aDirectLoginReference]); | ||
154 | }, | ||
155 | |||
156 | 'setDirectLoginIndexData': function (aDirectLoginReference, aKey, aValue) { | ||
157 | //if (MochiKit.Base.isUndefinedOrNull(this.directLoginsIndex()[aDirectLoginReference])) { | ||
158 | //throw "PIPPO"; | ||
159 | //} | ||
160 | return this.directLoginsData().setValue(this.directLoginsIndex()[aDirectLoginReference] + '.' + aKey, aValue); | ||
161 | }, | ||
162 | |||
163 | 'addDirectLoginIndexData': function (aDirectLoginReference) { | ||
164 | return this.directLoginsData().setValue(this.directLoginsIndex()[aDirectLoginReference], {}); | ||
165 | }, | ||
166 | |||
167 | 'removeDirectLoginIndexData': function (aDirectLoginReference) { | ||
168 | return this.directLoginsData().removeValue(this.directLoginsIndex()[aDirectLoginReference]) | ||
169 | }, | ||
170 | |||
171 | //------------------------------------------------------------------------- | ||
172 | |||
173 | 'records': function () { | ||
174 | vardeferredResult; | ||
175 | |||
176 | deferredResult = new Clipperz.Async.Deferred("User.Header.RecordIndex.records", {trace:false}); | ||
177 | deferredResult.acquireLock(this.lock()); | ||
178 | deferredResult.addCallback(MochiKit.Base.bind(function () { | ||
179 | var innerDeferredResult; | ||
180 | |||
181 | if (this._records == null) { | ||
182 | innerDeferredResult = new Clipperz.Async.Deferred("User.Header.RecordIndex.records <inner deferred>", {trace:false}); | ||
183 | innerDeferredResult.collectResults({ | ||
184 | 'records': [ | ||
185 | // MochiKit.Base.method(this.recordsData(), 'getObjectDataStore'), | ||
186 | // MochiKit.Base.methodcaller('values') | ||
187 | MochiKit.Base.method(this.recordsData(), 'values') | ||
188 | ], | ||
189 | 'recordsStats': [ | ||
190 | MochiKit.Base.method(this.recordsData(), 'getRemoteData'), | ||
191 | MochiKit.Base.itemgetter('recordsStats') | ||
192 | ], | ||
193 | 'directLogins': [ | ||
194 | // MochiKit.Base.method(this.directLoginsData(), 'getObjectDataStore'), | ||
195 | // MochiKit.Base.methodcaller('values') | ||
196 | MochiKit.Base.method(this.directLoginsData(), 'values') | ||
197 | ] | ||
198 | }) | ||
199 | innerDeferredResult.addCallback(MochiKit.Base.bind(function (someData) { | ||
200 | var indexReference; | ||
201 | var recordsInvertedIndex; | ||
202 | var directLoginsInvertedIndex; | ||
203 | |||
204 | recordsInvertedIndex = Clipperz.PM.DataModel.User.Header.RecordIndex.invertIndex(this.recordsIndex()); | ||
205 | directLoginsInvertedIndex= Clipperz.PM.DataModel.User.Header.RecordIndex.invertIndex(this.directLoginsIndex()); | ||
206 | |||
207 | this._records = {}; | ||
208 | |||
209 | for (indexReference in someData['records']) { | ||
210 | varrecord; | ||
211 | var reference; | ||
212 | var updateDate; | ||
213 | |||
214 | reference = recordsInvertedIndex[indexReference]; | ||
215 | |||
216 | if (typeof(someData['recordsStats'][reference]) != 'undefined') { | ||
217 | updateDate = someData['recordsStats'][reference]['updateDate']; | ||
218 | |||
219 | record = new Clipperz.PM.DataModel.Record({ | ||
220 | 'reference': reference, | ||
221 | 'retrieveKeyFunction': MochiKit.Base.method(this, 'getRecordKey'), | ||
222 | 'retrieveRemoteDataFunction':this.retrieveRecordDetailFunction(), | ||
223 | |||
224 | 'retrieveIndexDataFunction':MochiKit.Base.method(this, 'getRecordIndexData'), | ||
225 | 'updateIndexDataFunction': MochiKit.Base.method(this, 'updateRecordIndexData'), | ||
226 | 'updateDate': updateDate, | ||
227 | |||
228 | 'retrieveDirectLoginIndexDataFunction':MochiKit.Base.method(this, 'getDirectLoginIndexData'), | ||
229 | 'setDirectLoginIndexDataFunction': MochiKit.Base.method(this, 'setDirectLoginIndexData'), | ||
230 | 'removeDirectLoginIndexDataFunction':MochiKit.Base.method(this, 'removeDirectLoginIndexData'), | ||
231 | |||
232 | 'createNewDirectLoginFunction': MochiKit.Base.method(this, 'createNewDirectLogin') | ||
233 | }); | ||
234 | |||
235 | this._records[reference] = record; | ||
236 | } else { | ||
237 | Clipperz.log("SKIPPING record " + reference + " as there are no stas associated - " + Clipperz.Base.serializeJSON(someData['records'][reference])); | ||
238 | //# skip the record, as it seems it is not present in the DB | ||
239 | //updateDate = Clipperz.PM.Date.formatDateWithUTCFormat(new Date()); | ||
240 | } | ||
241 | } | ||
242 | |||
243 | for (indexReference in someData['directLogins']) { | ||
244 | // vardirectLogin; | ||
245 | var reference; | ||
246 | var record; | ||
247 | |||
248 | reference = directLoginsInvertedIndex[indexReference]; | ||
249 | record = this._records[recordsInvertedIndex[someData['directLogins'][indexReference]['record']]]; | ||
250 | |||
251 | if (record != null) { | ||
252 | // directLogin = new Clipperz.PM.DataModel.DirectLogin({ | ||
253 | new Clipperz.PM.DataModel.DirectLogin({ | ||
254 | 'reference': reference, | ||
255 | 'record': record | ||
256 | }); | ||
257 | } else { | ||
258 | Clipperz.logWarning("WARNING: DIRECT LOGIN without a matching RECORD!!"); | ||
259 | } | ||
260 | } | ||
261 | |||
262 | return this._records; | ||
263 | }, this)); | ||
264 | innerDeferredResult.callback(); | ||
265 | } else { | ||
266 | innerDeferredResult = MochiKit.Async.succeed(this._records); | ||
267 | } | ||
268 | |||
269 | return innerDeferredResult; | ||
270 | }, this)); | ||
271 | deferredResult.releaseLock(this.lock()); | ||
272 | deferredResult.callback(); | ||
273 | |||
274 | return deferredResult; | ||
275 | }, | ||
276 | |||
277 | //------------------------------------------------------------------------- | ||
278 | |||
279 | 'updateRecordIndexForNewRecord': function (aNewRecord) { | ||
280 | var newRecordIndex; | ||
281 | var recordReference; | ||
282 | |||
283 | recordReference = aNewRecord.reference(); | ||
284 | newRecordIndex = (MochiKit.Base.listMax(MochiKit.Base.map(MochiKit.Base.partial(MochiKit.Base.operator.mul, 1), MochiKit.Base.values(this.recordsIndex()))) + 1) + ''; | ||
285 | this.recordsIndex()[recordReference] = newRecordIndex; | ||
286 | |||
287 | this.transientState().setValue('newlyCreatedRecordsIndex' + '.' + recordReference, newRecordIndex); | ||
288 | this.transientState().setValue('newlyCreatedRecordsReferences'+ '.' + recordReference, aNewRecord); | ||
289 | }, | ||
290 | |||
291 | //......................................................................... | ||
292 | |||
293 | 'createNewRecord': function () { | ||
294 | var deferredResult; | ||
295 | var newRecord; | ||
296 | |||
297 | newRecord = new Clipperz.PM.DataModel.Record({ | ||
298 | 'retrieveKeyFunction': MochiKit.Base.method(this, 'getRecordKey'), | ||
299 | 'retrieveRemoteDataFunction':this.retrieveRecordDetailFunction(), | ||
300 | |||
301 | 'retrieveIndexDataFunction':MochiKit.Base.method(this, 'getRecordIndexData'), | ||
302 | 'updateIndexDataFunction': MochiKit.Base.method(this, 'updateRecordIndexData'), | ||
303 | 'updateDate': Clipperz.PM.Date.formatDateWithUTCFormat(new Date()), | ||
304 | |||
305 | 'retrieveDirectLoginIndexDataFunction':MochiKit.Base.method(this, 'getDirectLoginIndexData'), | ||
306 | 'setDirectLoginIndexDataFunction': MochiKit.Base.method(this, 'setDirectLoginIndexData'), | ||
307 | 'removeDirectLoginIndexDataFunction':MochiKit.Base.method(this, 'removeDirectLoginIndexData'), | ||
308 | |||
309 | 'createNewDirectLoginFunction': MochiKit.Base.method(this, 'createNewDirectLogin') | ||
310 | }); | ||
311 | |||
312 | this.transientState().setValue('newRecordsReferences' + '.' + newRecord.reference(), newRecord); | ||
313 | this.updateRecordIndexForNewRecord(newRecord); | ||
314 | |||
315 | deferredResult = Clipperz.Async.callbacks("User.Header.RecordIndex.createNewRecord", [ | ||
316 | MochiKit.Base.method(this, 'records'), | ||
317 | MochiKit.Base.partial(Clipperz.Async.setItemOnObject, newRecord.reference(), newRecord), | ||
318 | MochiKit.Base.method(this, 'setRecordKey', newRecord.reference(), Clipperz.PM.Crypto.randomKey()), | ||
319 | MochiKit.Base.method(newRecord, 'setLabel', ''), | ||
320 | MochiKit.Base.partial(MochiKit.Async.succeed, newRecord) | ||
321 | ], {trace:false}); | ||
322 | |||
323 | |||
324 | return deferredResult; | ||
325 | }, | ||
326 | |||
327 | //------------------------------------------------------------------------- | ||
328 | |||
329 | 'deleteRecord': function (aRecord) { | ||
330 | var deferredResult; | ||
331 | var recordReference; | ||
332 | |||
333 | recordReference = aRecord.reference(); | ||
334 | |||
335 | deferredResult = new Clipperz.Async.Deferred("User.Header.RecordIndex.deleteRecord", {trace:false}); | ||
336 | |||
337 | deferredResult.addMethod(aRecord, 'directLogins'); | ||
338 | deferredResult.addCallback(MochiKit.Base.values); | ||
339 | deferredResult.addCallback(MochiKit.Base.map, MochiKit.Base.method(this, 'removeDirectLogin')); | ||
340 | |||
341 | deferredResult.addMethod(this.recordsData(), 'removeValue', this.recordsIndex()[recordReference]); | ||
342 | deferredResult.addCallback(MochiKit.Base.bind(function () { | ||
343 | this.transientState().setValue('deleteRecordsIndex' + '.' + recordReference, this.recordsIndex()[recordReference]); | ||
344 | delete this.recordsIndex()[recordReference]; | ||
345 | }, this)); | ||
346 | |||
347 | deferredResult.addMethod(this, 'records'); | ||
348 | deferredResult.addCallback(MochiKit.Base.itemgetter(recordReference)); | ||
349 | deferredResult.addMethod(this.transientState(), 'setValue', 'deleteRecordsReferences' + '.' + recordReference); | ||
350 | |||
351 | deferredResult.addMethod(this, 'records'); | ||
352 | deferredResult.addCallback(MochiKit.Base.bind(function (someRecords) { | ||
353 | delete someRecords[recordReference]; | ||
354 | }, this)); | ||
355 | deferredResult.callback(); | ||
356 | |||
357 | return deferredResult; | ||
358 | }, | ||
359 | |||
360 | //========================================================================= | ||
361 | |||
362 | 'removeDirectLogin': function (aDirectLogin) { | ||
363 | this.directLoginsData().removeValue(this.directLoginsIndex()[aDirectLogin.reference()]); | ||
364 | }, | ||
365 | |||
366 | //------------------------------------------------------------------------- | ||
367 | |||
368 | 'createNewDirectLogin': function (aRecord) { | ||
369 | var newDirectLogin; | ||
370 | varnewDirectLoginIndexValue; | ||
371 | |||
372 | newDirectLogin = new Clipperz.PM.DataModel.DirectLogin({record:aRecord}); | ||
373 | newDirectLoginIndexValue = MochiKit.Base.listMax(MochiKit.Base.map(function (aValue) { return aValue * 1; }, MochiKit.Base.values(this.directLoginsIndex()))) + 1; | ||
374 | |||
375 | this.transientState().setValue('newDirectLoginReferences' + '.' + newDirectLogin.reference(), newDirectLogin); | ||
376 | |||
377 | this.directLoginsIndex()[newDirectLogin.reference()] = newDirectLoginIndexValue; | ||
378 | this.directLoginsData().setValue(this.directLoginsIndex()[newDirectLogin.reference()], {'record': this.recordsIndex()[aRecord.reference()]}); | ||
379 | |||
380 | return newDirectLogin; | ||
381 | }, | ||
382 | |||
383 | //========================================================================= | ||
384 | |||
385 | 'deleteAllCleanTextData': function () { | ||
386 | return Clipperz.Async.callbacks("User.Header.RecordIndex.deleteAllCleanTextData", [ | ||
387 | // MochiKit.Base.method(this, 'records'), | ||
388 | // MochiKit.Base.values, | ||
389 | // MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('deleteAllCleanTextData')), | ||
390 | |||
391 | MochiKit.Base.method(this, 'recordsData'), | ||
392 | MochiKit.Base.methodcaller('deleteAllCleanTextData'), | ||
393 | MochiKit.Base.method(this, 'directLoginsData'), | ||
394 | MochiKit.Base.methodcaller('deleteAllCleanTextData') | ||
395 | ], {trace:false}); | ||
396 | }, | ||
397 | |||
398 | //------------------------------------------------------------------------- | ||
399 | |||
400 | 'hasAnyCleanTextData': function () { | ||
401 | var deferredResult; | ||
402 | |||
403 | deferredResult = new Clipperz.Async.Deferred({trace:false}); | ||
404 | deferredResult.collectResults({ | ||
405 | 'recordsData': [ | ||
406 | MochiKit.Base.method(this, 'recordsData'), | ||
407 | MochiKit.Base.methodcaller('hasAnyCleanTextData') | ||
408 | ], | ||
409 | 'directLoginsData':[ | ||
410 | MochiKit.Base.method(this, 'directLoginsData'), | ||
411 | MochiKit.Base.methodcaller('hasAnyCleanTextData') | ||
412 | ], | ||
413 | // 'records': [ | ||
414 | // MochiKit.Base.method(this, 'records'), | ||
415 | // MochiKit.Base.values, | ||
416 | // MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('hasAnyCleanTextData')), | ||
417 | // Clipperz.Async.collectAll | ||
418 | // ] | ||
419 | }); | ||
420 | |||
421 | // deferredResult.addCallback(MochiKit.Base.values); | ||
422 | // deferredResult.addCallback(MochiKit.Base.flattenArguments); | ||
423 | // deferredResult.addCallback(function(someValues) { | ||
424 | // return MochiKit.Iter.some(someValues, MochiKit.Base.operator.identity); | ||
425 | // }); | ||
426 | deferredResult.addCallback(Clipperz.Async.or); | ||
427 | |||
428 | deferredResult.callback(); | ||
429 | |||
430 | return deferredResult; | ||
431 | }, | ||
432 | |||
433 | //------------------------------------------------------------------------- | ||
434 | |||
435 | 'hasPendingChanges': function () { | ||
436 | vardeferredResult; | ||
437 | |||
438 | deferredResult = new Clipperz.Async.Deferred("User.Header.RecordIndex.hasPendingChanges", {trace:false}); | ||
439 | deferredResult.collectResults({ | ||
440 | 'recordsData': [ | ||
441 | MochiKit.Base.method(this, 'recordsData'), | ||
442 | MochiKit.Base.methodcaller('hasPendingChanges') | ||
443 | ], | ||
444 | 'directLoginsData': [ | ||
445 | MochiKit.Base.method(this, 'directLoginsData'), | ||
446 | MochiKit.Base.methodcaller('hasPendingChanges') | ||
447 | ] | ||
448 | }); | ||
449 | deferredResult.addCallback(Clipperz.Async.or); | ||
450 | // deferredResult.addCallback(MochiKit.Base.values); | ||
451 | // deferredResult.addCallback(MochiKit.Base.flattenArguments); | ||
452 | // deferredResult.addCallback(function(someValues) { | ||
453 | // return MochiKit.Iter.some(someValues, MochiKit.Base.operator.identity); | ||
454 | // }); | ||
455 | deferredResult.callback(); | ||
456 | |||
457 | return deferredResult; | ||
458 | }, | ||
459 | |||
460 | //------------------------------------------------------------------------- | ||
461 | |||
462 | 'commitTransientState': function () { | ||
463 | var deferredResult; | ||
464 | |||
465 | deferredResut = Clipperz.Async.callbacks("User.Header.RecordIndex.commitTransientState", [ | ||
466 | MochiKit.Base.method(this, 'recordsData'), | ||
467 | MochiKit.Base.methodcaller('commitTransientState'), | ||
468 | |||
469 | MochiKit.Base.method(this, 'directLoginsData'), | ||
470 | MochiKit.Base.methodcaller('commitTransientState'), | ||
471 | |||
472 | MochiKit.Base.method(this, 'resetTransientState', true) | ||
473 | ], {trace:false}); | ||
474 | |||
475 | return deferredResult; | ||
476 | }, | ||
477 | |||
478 | //------------------------------------------------------------------------- | ||
479 | |||
480 | 'revertChanges': function () { | ||
481 | return Clipperz.Async.callbacks("User.Header.RecordIndex.revertChanges", [ | ||
482 | MochiKit.Base.method(this, 'recordsData'), | ||
483 | MochiKit.Base.methodcaller('revertChanges'), | ||
484 | |||
485 | // MochiKit.Base.method(this, 'directLoginsData'), | ||
486 | // MochiKit.Base.methodcaller('revertChanges'), | ||
487 | |||
488 | MochiKit.Base.method(this, 'records'), | ||
489 | MochiKit.Base.bind(function (someRecords) { | ||
490 | varrecordReference; | ||
491 | |||
492 | for (recordReference in this.transientState().getValue('deleteRecordsReferences')) { | ||
493 | this.recordsIndex()[recordReference] = this.transientState().getValue('deleteRecordsIndex' + '.' + recordReference); | ||
494 | someRecords[recordReference] = this.transientState().getValue('deleteRecordsReferences' + '.' + recordReference); | ||
495 | } | ||
496 | |||
497 | for (recordReference in this.transientState().getValue('newRecordsReferences')) { | ||
498 | delete this.recordsIndex()[recordReference]; | ||
499 | delete someRecords[recordReference]; | ||
500 | } | ||
501 | }, this), | ||
502 | |||
503 | // MochiKit.Base.method(this, 'directLogins'), | ||
504 | MochiKit.Base.bind(function () { | ||
505 | vardirectLoginReference; | ||
506 | |||
507 | //this.transientState().setValue('newDirectLoginReferences' + '.' + newDirectLogin.reference(), newDirectLogin); | ||
508 | // | ||
509 | //this.directLoginsIndex()[newDirectLogin.reference()] = newDirectLoginIndexValue; | ||
510 | //this.directLoginsData().setValue(this.directLoginsIndex()[newDirectLogin.reference()], {'record': this.recordsIndex()[aRecord.reference()]}); | ||
511 | |||
512 | |||
513 | // for (directLoginReference in this.transientState().getValue('deleteDirectLoginReferences')) { | ||
514 | // someDirectLogins[directLoginReference] = this.transientState().getValue('deleteDirectLoginReferences' + '.' + recordReference); | ||
515 | // } | ||
516 | |||
517 | for (directLoginReference in this.transientState().getValue('newDirectLoginReferences')) { | ||
518 | // this.directLoginsData().removeValue(this.directLoginsIndex()[directLoginReference]); | ||
519 | delete this.directLoginsIndex()[directLoginReference]; | ||
520 | } | ||
521 | }, this), | ||
522 | |||
523 | MochiKit.Base.method(this, 'directLoginsData'), | ||
524 | MochiKit.Base.methodcaller('revertChanges'), | ||
525 | |||
526 | MochiKit.Base.method(this, 'resetTransientState', false) | ||
527 | ], {trace:false}); | ||
528 | }, | ||
529 | |||
530 | //------------------------------------------------------------------------- | ||
531 | |||
532 | 'prepareRemoteDataWithKey': function (aKey) { | ||
533 | // "records": { | ||
534 | // "index": { | ||
535 | // "eeda70e0392261967bda71c3764da78989c45bbd2bb7be6b941b90f81d9b81b5": "0", | ||
536 | // "13a5e52976337ab210903cd04872588e1b21fb72bc183e91aa25c494b8138551": "1", | ||
537 | // ... | ||
538 | // "465a067a0bd2b470fa834de5397e38494de0c7707938262fae3427932e219744": "18", | ||
539 | // "4fd1dc2ca860b7fb47cef10a84edb3270da05510b0a30a6b0b083898712d4b9e": "19" | ||
540 | // }, | ||
541 | // "data": "n+AzGEEQXaSRSY4d ... BDypotrXgPo94uHfoXvGFzwCn8w=" | ||
542 | // }, | ||
543 | // "directLogins": { | ||
544 | // "index": { | ||
545 | // "61e87fdc4f1d9112e3b30c1f6812d095dcdb24f014c83319091eb6c9899ec348":"0", | ||
546 | // "989593d4c48929f0c8f1581aa96969c622807e99619ed4732026e967530a68ad":"1", | ||
547 | // ... | ||
548 | // "cb9ae0bba1957075ccdbfd3b3481704d62087687a2ac7c411a4f07d444bde0f7":"17", | ||
549 | // "7e1d069b7fa57c03bd7bf48807520feb953157834503aaff8c9d493f37dea69d":"18" | ||
550 | // }, | ||
551 | // "data":"5YG9KKU/OZ5guUgFlms6k1 ... ZG/5Fn0uN+LoAsNfHm+EE62x" | ||
552 | // }, | ||
553 | |||
554 | var deferredResult; | ||
555 | var result; | ||
556 | |||
557 | result = {}; | ||
558 | |||
559 | deferredResult = new Clipperz.Async.Deferred("User.Header.RecordIndex.prepareRemoteDataWithKey", {trace:false}); | ||
560 | deferredResult.collectResults({ | ||
561 | 'index':MochiKit.Base.partial(MochiKit.Async.succeed, this.recordsIndex()), | ||
562 | 'data': [ | ||
563 | MochiKit.Base.method(this.recordsData(), 'prepareRemoteDataWithKey', aKey), | ||
564 | MochiKit.Base.itemgetter('data') | ||
565 | ] | ||
566 | }); | ||
567 | deferredResult.addCallback(Clipperz.Async.setItem, result, 'records'); | ||
568 | |||
569 | deferredResult.collectResults({ | ||
570 | 'index':MochiKit.Base.partial(MochiKit.Async.succeed, this.directLoginsIndex()), | ||
571 | 'data': [ | ||
572 | MochiKit.Base.method(this.directLoginsData(), 'prepareRemoteDataWithKey', aKey), | ||
573 | MochiKit.Base.itemgetter('data') | ||
574 | ] | ||
575 | }); | ||
576 | deferredResult.addCallback(Clipperz.Async.setItem, result, 'directLogins'); | ||
577 | |||
578 | deferredResult.addCallback(MochiKit.Async.succeed, result); | ||
579 | |||
580 | deferredResult.callback(); | ||
581 | |||
582 | return deferredResult; | ||
583 | }, | ||
584 | |||
585 | //------------------------------------------------------------------------- | ||
586 | |||
587 | 'updateRecordKeyAndPrepareRemoteData': function (aRecord) { | ||
588 | varnewRecordKey; | ||
589 | var deferredResult; | ||
590 | |||
591 | newRecordKey = Clipperz.PM.Crypto.randomKey(); | ||
592 | |||
593 | deferredResult = new Clipperz.Async.Deferred("User.Header.RecordIndex.updateRecordKeyAndPrepareRemoteData", {trace:false}); | ||
594 | deferredResult.addCallback(MochiKit.Base.method(aRecord, 'prepareRemoteDataWithKey', newRecordKey)); | ||
595 | deferredResult.addCallbackPass(MochiKit.Base.method(this, 'setRecordKey', aRecord.reference(), newRecordKey)); | ||
596 | deferredResult.callback(); | ||
597 | |||
598 | return deferredResult; | ||
599 | }, | ||
600 | |||
601 | //......................................................................... | ||
602 | |||
603 | 'removeNewRecordWithNoChanges': function (aRecord) { | ||
604 | var deferredResult; | ||
605 | var recordReference; | ||
606 | |||
607 | recordReference = aRecord.reference(); | ||
608 | |||
609 | deferredResult = new Clipperz.Async.Deferred("User.Header.RecordIndex.removeNewRecordWithNoChanges", {trace:false}); | ||
610 | |||
611 | deferredResult.addMethod(this.recordsData(), 'removeValue', this.recordsIndex()[recordReference]); | ||
612 | deferredResult.addCallback(MochiKit.Base.bind(function () { | ||
613 | delete this.recordsIndex()[recordReference]; | ||
614 | }, this)); | ||
615 | |||
616 | deferredResult.addMethod(this, 'records'); | ||
617 | deferredResult.addCallback(MochiKit.Base.bind(function (someRecords) { | ||
618 | delete someRecords[recordReference]; | ||
619 | }, this)); | ||
620 | deferredResult.callback(); | ||
621 | |||
622 | return deferredResult; | ||
623 | }, | ||
624 | |||
625 | //......................................................................... | ||
626 | |||
627 | 'prepareRemoteDataForChangedRecords': function () { | ||
628 | vardeferredResult; | ||
629 | varresult; | ||
630 | |||
631 | result = {}; | ||
632 | |||
633 | deferredResult = new Clipperz.Async.Deferred("User.Header.RecordIndex.prepareRemoteDataForChangedRecords", {trace:false}); | ||
634 | |||
635 | deferredResult.addMethod(this, 'records'); | ||
636 | deferredResult.addCallback(MochiKit.Base.values); | ||
637 | deferredResult.addCallback(Clipperz.Async.deferredFilter, MochiKit.Base.methodcaller('isBrandNewWithNoPendingChanges')); | ||
638 | deferredResult.addCallback(MochiKit.Base.map, MochiKit.Base.method(this, 'removeNewRecordWithNoChanges')); | ||
639 | |||
640 | deferredResult.addMethod(this, 'records'); | ||
641 | deferredResult.addCallback(MochiKit.Base.values); | ||
642 | deferredResult.addCallback(Clipperz.Async.deferredFilter, MochiKit.Base.methodcaller('hasPendingChanges')); | ||
643 | deferredResult.addCallback(MochiKit.Base.map, MochiKit.Base.method(this, 'updateRecordKeyAndPrepareRemoteData')); | ||
644 | deferredResult.addCallback(Clipperz.Async.collectAll); | ||
645 | |||
646 | deferredResult.addCallback(Clipperz.Async.deferredIf("updated records != null", [ | ||
647 | MochiKit.Base.operator.identity | ||
648 | ], [ | ||
649 | MochiKit.Base.partial(MochiKit.Async.succeed, []) | ||
650 | ])); | ||
651 | deferredResult.addCallback(Clipperz.Async.setItem, result, 'updated'); | ||
652 | |||
653 | deferredResult.addMethod(this.transientState(), 'getValue', 'deleteRecordsReferences'); | ||
654 | deferredResult.addCallback(MochiKit.Base.keys); | ||
655 | deferredResult.addCallback(Clipperz.Async.deferredIf("deleted records != null", [ | ||
656 | MochiKit.Base.operator.identity | ||
657 | ], [ | ||
658 | MochiKit.Base.partial(MochiKit.Async.succeed, []) | ||
659 | ])); | ||
660 | deferredResult.addCallback(Clipperz.Async.setItem, result, 'deleted'); | ||
661 | |||
662 | deferredResult.addCallback(MochiKit.Async.succeed, result); | ||
663 | deferredResult.callback(); | ||
664 | |||
665 | return deferredResult; | ||
666 | }, | ||
667 | |||
668 | //------------------------------------------------------------------------- | ||
669 | __syntaxFix__: "syntax fix" | ||
670 | }); | ||
671 | |||
672 | |||
673 | |||
674 | Clipperz.PM.DataModel.User.Header.RecordIndex.invertIndex = function (anIndex) { | ||
675 | var result; | ||
676 | var key; | ||
677 | |||
678 | result = {}; | ||
679 | |||
680 | for (key in anIndex) { | ||
681 | result[anIndex[key]] = key; | ||
682 | } | ||
683 | |||
684 | return result; | ||
685 | }; \ No newline at end of file | ||
diff --git a/frontend/delta/js/Clipperz/PM/DataModel/User.Subscription.js b/frontend/delta/js/Clipperz/PM/DataModel/User.Subscription.js new file mode 100644 index 0000000..341e9f3 --- a/dev/null +++ b/frontend/delta/js/Clipperz/PM/DataModel/User.Subscription.js | |||
@@ -0,0 +1,53 @@ | |||
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 | try { if (typeof(Clipperz.PM.DataModel.User) == 'undefined') { throw ""; }} catch (e) { | ||
25 | throw "Clipperz.PM.DataModel.User.Subscription depends on Clipperz.PM.DataModel.User!"; | ||
26 | } | ||
27 | |||
28 | Clipperz.PM.DataModel.User.Subscription = function(args) { | ||
29 | this._attributes = args; | ||
30 | return this; | ||
31 | } | ||
32 | |||
33 | |||
34 | Clipperz.Base.extend(Clipperz.PM.DataModel.User.Subscription, Object, { | ||
35 | |||
36 | 'features': function () { | ||
37 | return this._attributes['features']; | ||
38 | }, | ||
39 | |||
40 | 'type': function () { | ||
41 | return this._attributes['type']; | ||
42 | }, | ||
43 | |||
44 | 'validity': function () { | ||
45 | return { | ||
46 | 'from':this._attributes['fromDate'], | ||
47 | 'to':this._attributes['toDate'] | ||
48 | }; | ||
49 | }, | ||
50 | |||
51 | //========================================================================= | ||
52 | __syntaxFix__: "syntax fix" | ||
53 | }); | ||
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 | //----------------------------------------------------------------------------- | ||