summaryrefslogtreecommitdiff
path: root/frontend/gamma/js/Clipperz/PM/DataModel/EncryptedRemoteObject.js
Unidiff
Diffstat (limited to 'frontend/gamma/js/Clipperz/PM/DataModel/EncryptedRemoteObject.js') (more/less context) (ignore whitespace changes)
-rw-r--r--frontend/gamma/js/Clipperz/PM/DataModel/EncryptedRemoteObject.js551
1 files changed, 551 insertions, 0 deletions
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});