Diffstat (limited to 'frontend/delta/js/Clipperz/PM/UI/MainController.js') (more/less context) (ignore whitespace changes)
-rw-r--r-- | frontend/delta/js/Clipperz/PM/UI/MainController.js | 491 |
1 files changed, 491 insertions, 0 deletions
diff --git a/frontend/delta/js/Clipperz/PM/UI/MainController.js b/frontend/delta/js/Clipperz/PM/UI/MainController.js new file mode 100644 index 0000000..da7540e --- a/dev/null +++ b/frontend/delta/js/Clipperz/PM/UI/MainController.js | |||
@@ -0,0 +1,491 @@ | |||
1 | /* | ||
2 | |||
3 | Copyright 2008-2013 Clipperz Srl | ||
4 | |||
5 | This file is part of Clipperz, the online password manager. | ||
6 | For further information about its features and functionalities please | ||
7 | refer to http://www.clipperz.com. | ||
8 | |||
9 | * Clipperz is free software: you can redistribute it and/or modify it | ||
10 | under the terms of the GNU Affero General Public License as published | ||
11 | by the Free Software Foundation, either version 3 of the License, or | ||
12 | (at your option) any later version. | ||
13 | |||
14 | * Clipperz is distributed in the hope that it will be useful, but | ||
15 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
17 | See the GNU Affero General Public License for more details. | ||
18 | |||
19 | * You should have received a copy of the GNU Affero General Public | ||
20 | License along with Clipperz. If not, see http://www.gnu.org/licenses/. | ||
21 | |||
22 | */ | ||
23 | |||
24 | Clipperz.Base.module('Clipperz.PM.UI'); | ||
25 | |||
26 | Clipperz.PM.UI.MainController = function() { | ||
27 | var pages; | ||
28 | |||
29 | this._proxy = null; | ||
30 | this._user = null; | ||
31 | this._filter= ''; | ||
32 | |||
33 | //this._currentPage = 'loadingPage'; | ||
34 | |||
35 | this._pageStack = ['loadingPage']; | ||
36 | this._overlay = new Clipperz.PM.UI.Components.Overlay(); | ||
37 | pages = { | ||
38 | 'loginPage': new Clipperz.PM.UI.Components.LoginForm(), | ||
39 | 'registrationPage':new Clipperz.PM.UI.Components.RegistrationWizard(), | ||
40 | 'cardListPage': new Clipperz.PM.UI.Components.CardList(), | ||
41 | 'cardDetailPage':new Clipperz.PM.UI.Components.CardDetail({card: {}}), | ||
42 | 'errorPage': new Clipperz.PM.UI.Components.ErrorPage({message:''}) | ||
43 | }; | ||
44 | |||
45 | MochiKit.Base.map(function (anId) {React.renderComponent(pages[anId], MochiKit.DOM.getElement(anId))}, MochiKit.Base.keys(pages)); | ||
46 | this._pages = pages; | ||
47 | this.registerForNotificationCenterEvents(); | ||
48 | |||
49 | return this; | ||
50 | } | ||
51 | |||
52 | MochiKit.Base.update(Clipperz.PM.UI.MainController.prototype, { | ||
53 | |||
54 | toString: function () { | ||
55 | return "Clipperz.PM.UI.MainController"; | ||
56 | }, | ||
57 | |||
58 | //========================================================================= | ||
59 | |||
60 | overlay: function () { | ||
61 | return this._overlay; | ||
62 | }, | ||
63 | |||
64 | loginForm: function () { | ||
65 | return this._loginForm; | ||
66 | }, | ||
67 | |||
68 | registrationWizard: function () { | ||
69 | return this._registrationWizard; | ||
70 | }, | ||
71 | |||
72 | //========================================================================= | ||
73 | |||
74 | isOnline: function() { | ||
75 | return navigator.onLine; | ||
76 | }, | ||
77 | |||
78 | hasLocalData: function() { | ||
79 | return false; | ||
80 | }, | ||
81 | |||
82 | loginMode: function () { | ||
83 | //PIN is set using this command: | ||
84 | //Clipperz.PM.PIN.setCredentialsWithPIN('1234', {'username':'joe', 'passphrase':'clipperz'}); | ||
85 | |||
86 | return Clipperz.PM.PIN.isSet() ? 'PIN' : 'CREDENTIALS'; | ||
87 | }, | ||
88 | |||
89 | //========================================================================= | ||
90 | |||
91 | pages: function () { | ||
92 | return this._pages; | ||
93 | }, | ||
94 | |||
95 | pageStack: function () { | ||
96 | return this._pageStack; | ||
97 | }, | ||
98 | |||
99 | //========================================================================= | ||
100 | |||
101 | selectInitialProxy: function () { | ||
102 | if (this.isOnline()) { | ||
103 | this._proxy = Clipperz.PM.Proxy.defaultProxy; | ||
104 | } else { | ||
105 | if (this.hasLocalData()) { | ||
106 | this._proxy = new Clipperz.PM.Proxy.Offline({dataStore: new Clipperz.PM.Proxy.Offline.LocalStorageDataStore(), shouldPayTolls:false}); | ||
107 | } else { | ||
108 | this.showOfflineError(); | ||
109 | } | ||
110 | } | ||
111 | }, | ||
112 | |||
113 | proxy: function () { | ||
114 | return this._proxy; | ||
115 | }, | ||
116 | |||
117 | //========================================================================= | ||
118 | |||
119 | registerForNotificationCenterEvents: function () { | ||
120 | var events= ['doLogin', 'registerNewUser', 'showRegistrationForm', 'goBack', 'showRecord', 'searchCards', 'runDirectLogin']; | ||
121 | var self= this; | ||
122 | |||
123 | MochiKit.Base.map(function (anEvent) { | ||
124 | MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, anEvent, MochiKit.Base.method(self, anEvent)); | ||
125 | }, events); | ||
126 | |||
127 | // MochiKit.Signal.connect(window, 'onpopstate', MochiKit.Base.method(this, 'historyGoBack')); | ||
128 | MochiKit.Signal.connect(window, 'onbeforeunload',MochiKit.Base.method(this, 'shouldExitApp')); | ||
129 | }, | ||
130 | |||
131 | //------------------------------------------------------------------------- | ||
132 | |||
133 | run: function (parameters) { | ||
134 | var shouldShowRegistrationForm; | ||
135 | |||
136 | this.selectInitialProxy(); | ||
137 | shouldShowRegistrationForm = parameters['shouldShowRegistrationForm'] && this.proxy().canRegisterNewUsers(); | ||
138 | this.pages()['loginPage'].setProps({'mode':this.loginMode(), 'isNewUserRegistrationAvailable': this.proxy().canRegisterNewUsers()}); | ||
139 | |||
140 | if (shouldShowRegistrationForm) { | ||
141 | this.showRegistrationForm(); | ||
142 | } else { | ||
143 | this.showLoginForm(); | ||
144 | } | ||
145 | this.overlay().done("", 0.5); | ||
146 | }, | ||
147 | |||
148 | //------------------------------------------------------------------------- | ||
149 | |||
150 | showLoginForm: function () { | ||
151 | varloginFormPage; | ||
152 | |||
153 | loginFormPage = this.pages()['loginPage']; | ||
154 | loginFormPage.setProps({'mode':this.loginMode(), 'isNewUserRegistrationAvailable': this.proxy().canRegisterNewUsers()}); | ||
155 | this.moveInPage(this.currentPage(), 'loginPage'); | ||
156 | MochiKit.Async.callLater(0.5, MochiKit.Base.method(loginFormPage, 'setInitialFocus')); | ||
157 | }, | ||
158 | |||
159 | showRegistrationForm: function () { | ||
160 | var currentPage; | ||
161 | varregistrationPage; | ||
162 | |||
163 | currentPage = this.currentPage(); | ||
164 | registrationPage = this.pages()['registrationPage']; | ||
165 | this.setCurrentPage('loginPage'); | ||
166 | registrationPage.setProps({}); | ||
167 | this.moveInPage(currentPage, 'registrationPage'); | ||
168 | MochiKit.Async.callLater(0.5, MochiKit.Base.method(registrationPage, 'setInitialFocus')); | ||
169 | }, | ||
170 | |||
171 | //========================================================================= | ||
172 | |||
173 | doLogin: function (event) { | ||
174 | varcredentials; | ||
175 | var getPassphraseDelegate; | ||
176 | varuser; | ||
177 | |||
178 | user = null; | ||
179 | |||
180 | this.overlay().show("logging in"); | ||
181 | this.pages()['loginPage'].setProps({disabled:true}); | ||
182 | |||
183 | if ('pin' in event) { | ||
184 | credentials = Clipperz.PM.PIN.credentialsWithPIN(event['pin']); | ||
185 | } else { | ||
186 | credentials = event; | ||
187 | } | ||
188 | getPassphraseDelegate = MochiKit.Base.partial(MochiKit.Async.succeed, credentials.passphrase); | ||
189 | user = new Clipperz.PM.DataModel.User({'username':credentials.username, 'getPassphraseFunction':getPassphraseDelegate}); | ||
190 | |||
191 | deferredResult = new Clipperz.Async.Deferred('MainController.doLogin', {trace:false}); | ||
192 | deferredResult.addCallback(MochiKit.Async.wait, 0.1); | ||
193 | deferredResult.addMethod(Clipperz.Crypto.PRNG.defaultRandomGenerator(), 'deferredEntropyCollection'); | ||
194 | deferredResult.addMethod(user, 'login'); | ||
195 | deferredResult.addMethod(Clipperz.PM.PIN, 'resetFailedAttemptCount'); | ||
196 | deferredResult.addMethod(this, 'setUser', user); | ||
197 | |||
198 | // deferredResult.addMethod(this, 'setupApplication'); | ||
199 | deferredResult.addMethod(this, 'runApplication'); | ||
200 | deferredResult.addMethod(this.overlay(), 'done', "", 1); | ||
201 | deferredResult.addErrback(MochiKit.Base.method(this, 'genericErrorHandler', event)); | ||
202 | deferredResult.addErrback(MochiKit.Base.bind(function (anEvent, anError) { | ||
203 | if (anError['isPermanent'] != true) { | ||
204 | this.pages()['loginPage'].setProps({disabled:false, 'mode':this.loginMode()}); | ||
205 | this.pages()['loginPage'].setInitialFocus(); | ||
206 | } | ||
207 | return anError; | ||
208 | }, this, event)) | ||
209 | deferredResult.callback(); | ||
210 | |||
211 | return deferredResult; | ||
212 | }, | ||
213 | |||
214 | //------------------------------------------------------------------------- | ||
215 | |||
216 | registerNewUser: function (credentials) { | ||
217 | vardeferredResult; | ||
218 | |||
219 | this.overlay().show("creating user"); | ||
220 | |||
221 | this.pages()['registrationPage'].setProps({disabled:true}); | ||
222 | deferredResult = new Clipperz.Async.Deferred('MainController.registerNewUser', {trace:false}); | ||
223 | deferredResult.addCallback(Clipperz.PM.DataModel.User.registerNewAccount, | ||
224 | credentials['username'], | ||
225 | MochiKit.Base.partial(MochiKit.Async.succeed, credentials['passphrase']) | ||
226 | ); | ||
227 | deferredResult.addMethod(this, 'doLogin', credentials); | ||
228 | deferredResult.addErrback(MochiKit.Base.method(this, 'genericErrorHandler', event)); | ||
229 | deferredResult.addErrback(MochiKit.Base.bind(function (anError) { | ||
230 | if (anError['isPermanent'] != true) { | ||
231 | this.pages()['registrationPage'].setProps({disabled:false}); | ||
232 | this.pages()['registrationPage'].setInitialFocus(); | ||
233 | } | ||
234 | return anError; | ||
235 | }, this)); | ||
236 | |||
237 | deferredResult.callback(); | ||
238 | |||
239 | return deferredResult; | ||
240 | |||
241 | }, | ||
242 | |||
243 | //------------------------------------------------------------------------- | ||
244 | |||
245 | user: function () { | ||
246 | return this._user; | ||
247 | }, | ||
248 | |||
249 | setUser: function (aUser) { | ||
250 | this._user = aUser; | ||
251 | return this._user; | ||
252 | }, | ||
253 | |||
254 | //========================================================================= | ||
255 | |||
256 | allCardInfo: function () { | ||
257 | var deferredResult; | ||
258 | varcardInfo; | ||
259 | |||
260 | cardInfo = { | ||
261 | '_rowObject': MochiKit.Async.succeed, | ||
262 | '_reference': MochiKit.Base.methodcaller('reference'), | ||
263 | '_searchableContent':MochiKit.Base.methodcaller('searchableContent'), | ||
264 | 'label': MochiKit.Base.methodcaller('label'), | ||
265 | 'favicon': MochiKit.Base.methodcaller('favicon') | ||
266 | }; | ||
267 | |||
268 | deferredResult = new Clipperz.Async.Deferred('MainController.allCardInfo', {trace:false}); | ||
269 | deferredResult.addMethod(this.user(), 'getRecords'); | ||
270 | deferredResult.addCallback(MochiKit.Base.map, Clipperz.Async.collectResults("CardList.value - collectResults", cardInfo, {trace:false})); | ||
271 | deferredResult.addCallback(Clipperz.Async.collectAll); | ||
272 | deferredResult.callback(); | ||
273 | |||
274 | return deferredResult; | ||
275 | }, | ||
276 | |||
277 | filterCards: function (someCardInfo) { | ||
278 | var filter; | ||
279 | varfilterRegExp; | ||
280 | varresult; | ||
281 | |||
282 | filter = this.filter().replace(/[^A-Za-z0-9]/g, "\\$&"); | ||
283 | filterRegExp = new RegExp(filter, "i"); | ||
284 | result = MochiKit.Base.filter(function (aCardInfo) { return filterRegExp.test(aCardInfo['_searchableContent'])}, someCardInfo); | ||
285 | |||
286 | return result; | ||
287 | }, | ||
288 | |||
289 | sortCards: function (someCardInfo) { | ||
290 | return someCardInfo.sort(Clipperz.Base.caseInsensitiveKeyComparator('label')); | ||
291 | }, | ||
292 | |||
293 | showRecordList: function () { | ||
294 | var deferredResult; | ||
295 | |||
296 | deferredResult = new Clipperz.Async.Deferred('MainController.showRecordList', {trace:false}); | ||
297 | deferredResult.addMethod(this, 'allCardInfo'); | ||
298 | deferredResult.addMethod(this, 'filterCards'); | ||
299 | deferredResult.addMethod(this, 'sortCards'); | ||
300 | deferredResult.addCallback(MochiKit.Base.bind(function (someRecordInfo) { | ||
301 | this.pages()['cardListPage'].setProps({cardList: someRecordInfo}); | ||
302 | }, this)); | ||
303 | deferredResult.callback(); | ||
304 | |||
305 | return deferredResult; | ||
306 | }, | ||
307 | |||
308 | filter: function (){ | ||
309 | return this._filter; | ||
310 | }, | ||
311 | |||
312 | setFilter: function (aValue) { | ||
313 | this._filter = aValue; | ||
314 | }, | ||
315 | |||
316 | searchCards: function (someParameters) { | ||
317 | //console.log("SEARCH CARDS", someParameters); | ||
318 | this.setFilter(someParameters); | ||
319 | this.showRecordList(); | ||
320 | }, | ||
321 | |||
322 | //========================================================================= | ||
323 | |||
324 | runApplication: function () { | ||
325 | MochiKit.Signal.connect(window, 'onpopstate',MochiKit.Base.method(this, 'historyGoBack')); | ||
326 | this.moveInPage(this.currentPage(), 'cardListPage'); | ||
327 | return this.showRecordList(); | ||
328 | }, | ||
329 | |||
330 | showRecord: function (aRecordReference) { | ||
331 | //console.log("Show Record", aRecordReference); | ||
332 | vardeferredResult; | ||
333 | |||
334 | this.pages()['cardListPage'].setProps({selectedCard:aRecordReference}); | ||
335 | deferredResult = new Clipperz.Async.Deferred('MainController.runApplication', {trace:false}); | ||
336 | // deferredResult.addMethod(this.user(), 'getRecord', aRecordReference['_reference']); | ||
337 | deferredResult.addMethod(this.user(), 'getRecord', aRecordReference); | ||
338 | deferredResult.addMethodcaller('content'); | ||
339 | deferredResult.addCallback(MochiKit.Base.bind(function (aCard) { | ||
340 | //console.log("CARD DETAILS", aCard); | ||
341 | this.pages()['cardDetailPage'].setProps({card: aCard}); | ||
342 | this.pages()['cardListPage'].setProps({selectedCard: null}); | ||
343 | }, this)); | ||
344 | deferredResult.addMethod(this, 'moveInPage', this.currentPage(), 'cardDetailPage', true); | ||
345 | deferredResult.callback(); | ||
346 | |||
347 | return deferredResult; | ||
348 | }, | ||
349 | |||
350 | runDirectLogin: function (someParameters) { | ||
351 | console.log("RUN DIRECT LOGIN", someParameters); | ||
352 | vardeferredResult; | ||
353 | |||
354 | // this.pages()['cardListPage'].setProps({selectedCard:aRecordReference}); | ||
355 | deferredResult = new Clipperz.Async.Deferred('MainController.runDirectLogin', {trace:false}); | ||
356 | // deferredResult.addMethod(this.user(), 'getRecord', aRecordReference['_reference']); | ||
357 | deferredResult.addMethod(this.user(), 'getRecord', someParameters['record']); | ||
358 | deferredResult.addMethodcaller('directLoginWithReference', someParameters['directLogin']); | ||
359 | deferredResult.addCallback(Clipperz.PM.UI.DirectLoginRunner.openDirectLogin); | ||
360 | deferredResult.callback(); | ||
361 | |||
362 | return deferredResult; | ||
363 | }, | ||
364 | |||
365 | shouldExitApp: function (anEvent) { | ||
366 | console.log("SHOULD EXIT APP"); | ||
367 | anEvent.preventDefault(); | ||
368 | anEvent.stopPropagation(); | ||
369 | }, | ||
370 | |||
371 | //========================================================================= | ||
372 | |||
373 | genericErrorHandler: function (anEvent, anError) { | ||
374 | var errorMessage; | ||
375 | varresult; | ||
376 | |||
377 | result = anError; | ||
378 | errorMessage = "login failed"; | ||
379 | |||
380 | if (anError['isPermanent'] === true) { | ||
381 | this.pages()['errorPage'].setProps({message:anError.message}); | ||
382 | this.moveInPage(this.currentPage(), 'errorPage'); | ||
383 | errorMessage = "failure"; | ||
384 | } else { | ||
385 | if ('pin' in anEvent) { | ||
386 | errorCount = Clipperz.PM.PIN.recordFailedAttempt(); | ||
387 | if (errorCount == -1) { | ||
388 | errorMessage = "PIN resetted"; | ||
389 | } | ||
390 | } | ||
391 | } | ||
392 | this.overlay().failed(errorMessage, 1); | ||
393 | |||
394 | return result; | ||
395 | }, | ||
396 | |||
397 | //========================================================================= | ||
398 | |||
399 | slidePage: function (fromPage, toPage, direction) { | ||
400 | varfromPosition; | ||
401 | var toPosition; | ||
402 | |||
403 | if (direction == "LEFT") { | ||
404 | fromPosition = 'right'; | ||
405 | toPosition = 'left' | ||
406 | } else { | ||
407 | fromPosition = 'left'; | ||
408 | toPosition = 'right' | ||
409 | } | ||
410 | |||
411 | MochiKit.DOM.addElementClass(fromPage, toPosition + ' transition'); | ||
412 | |||
413 | MochiKit.DOM.addElementClass(toPage, fromPosition); | ||
414 | MochiKit.DOM.removeElementClass(toPage, toPosition); | ||
415 | MochiKit.DOM.addElementClass(toPage, 'transition'); | ||
416 | MochiKit.Async.callLater(0.1, function () { | ||
417 | MochiKit.DOM.removeElementClass(toPage, fromPosition); | ||
418 | }) | ||
419 | |||
420 | MochiKit.Async.callLater(0.5, function () { | ||
421 | MochiKit.DOM.removeElementClass(fromPage, 'transition'); | ||
422 | MochiKit.DOM.removeElementClass(toPage, 'transition'); | ||
423 | }) | ||
424 | }, | ||
425 | |||
426 | rotateInPage: function (fromPage, toPage) { | ||
427 | //Broken! :( | ||
428 | MochiKit.DOM.addElementClass(MochiKit.DOM.getElement('mainDiv'), 'show-right'); | ||
429 | }, | ||
430 | |||
431 | //......................................................................... | ||
432 | |||
433 | goBack: function () { | ||
434 | varfromPage; | ||
435 | var toPage; | ||
436 | |||
437 | fromPage = this.pageStack().shift(); | ||
438 | toPage = this.currentPage(); | ||
439 | this.pages()[toPage].setProps({}); | ||
440 | this.moveOutPage(fromPage, toPage); | ||
441 | }, | ||
442 | |||
443 | historyGoBack: function (anEvent) { | ||
444 | anEvent.preventDefault(); | ||
445 | anEvent.stopPropagation(); | ||
446 | this.goBack(); | ||
447 | }, | ||
448 | |||
449 | currentPage: function () { | ||
450 | return this.pageStack()[0]; | ||
451 | }, | ||
452 | |||
453 | setCurrentPage: function (aPage) { | ||
454 | this.pageStack().unshift(aPage); | ||
455 | }, | ||
456 | |||
457 | moveInPage: function (fromPage, toPage, addToHistory) { | ||
458 | varshouldAddItemToHistory; | ||
459 | |||
460 | shouldAddItemToHistory = typeof(addToHistory) == 'undefined' ? false : addToHistory; | ||
461 | |||
462 | this.slidePage(MochiKit.DOM.getElement(fromPage), MochiKit.DOM.getElement(toPage), 'LEFT'); | ||
463 | this.setCurrentPage(toPage); | ||
464 | |||
465 | if (shouldAddItemToHistory) { | ||
466 | //console.log("ADD ITEM TO HISTORY"); | ||
467 | //console.log("ADD ITEM TO HISTORY - window", window); | ||
468 | //console.log("ADD ITEM TO HISTORY - window.history", window.history); | ||
469 | window.history.pushState({'fromPage': fromPage, 'toPage': toPage}); | ||
470 | //# window.history.pushState(); | ||
471 | //console.log("ADDED ITEM TO HISTORY"); | ||
472 | } else { | ||
473 | //console.log("Skip HISTORY"); | ||
474 | } | ||
475 | }, | ||
476 | |||
477 | moveOutPage: function (fromPage, toPage) { | ||
478 | this.slidePage(MochiKit.DOM.getElement(fromPage), MochiKit.DOM.getElement(toPage), 'RIGHT'); | ||
479 | this.setCurrentPage(toPage); | ||
480 | }, | ||
481 | |||
482 | //========================================================================= | ||
483 | /* | ||
484 | wrongAppVersion: function (anError) { | ||
485 | // this.pages()['errorPage'].setProps({message:anError.message}); | ||
486 | // this.moveInPage('errorPage', this.currentPage()); | ||
487 | }, | ||
488 | */ | ||
489 | //========================================================================= | ||
490 | __syntaxFix__: "syntax fix" | ||
491 | }); | ||