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