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