From b3967dae52aa2ea10fdbc0e5739fbdcdd03d8d5b Mon Sep 17 00:00:00 2001 From: Giulio Cesare Solaroli Date: Thu, 9 Oct 2014 13:55:45 +0200 Subject: [PATCH] Fixes to release developer preview of the /delta version /delta needs an updated backend to support its payment options. /beta and /gamma have been updated to be compatible with the new backend. --- .gitignore | 4 +- frontend/beta/js/Clipperz/Crypto/PRNG.js | 4 +- frontend/delta/html/index_template.html | 4 +- .../PM/DataModel/EncryptedRemoteObject.js | 5 +- frontend/delta/js/main.js | 4 +- frontend/gamma/html/index_template.html | 1 + frontend/gamma/js/Clipperz/Base.js | 4 + frontend/gamma/js/Clipperz/Crypto/PRNG.js | 4 +- frontend/gamma/js/Clipperz/Date.js | 7 + .../PM/DataModel/Record.Version.Field.js | 6 +- .../Clipperz/PM/DataModel/User.AccountInfo.js | 94 +++++++ .../gamma/js/Clipperz/PM/DataModel/User.js | 32 ++- .../UI/Mobile/Controllers/MainController.js | 2 +- .../PM/UI/Web/Components/AccountPanel.js | 81 +++++- .../CardDialogRecordFieldComponent.js | 4 + .../PM/UI/Web/Components/LoginForm.js | 14 +- .../PM/UI/Web/Components/PaymentComponent.js | 220 +++++++++++++++ .../PM/UI/Web/Components/UserInfoBox.js | 258 ++++++++---------- .../PM/UI/Web/Controllers/AppController.js | 66 ++++- .../Web/Controllers/CardDialogController.js | 3 + .../PM/UI/Web/Controllers/MainController.js | 2 +- .../Controllers/NewUserWizardController.js | 1 + .../UI/Web/Controllers/PaymentController.js | 111 ++++++++ .../gamma/properties/gamma.properties.json | 3 + .../gamma/tests/tests/Clipperz/Base.test.js | 21 ++ .../Clipperz/PM/DataModel/DirectLogin.html | 1 + .../PM/DataModel/OneTimePassword.html | 1 + .../tests/Clipperz/PM/DataModel/Record.html | 1 + .../tests/Clipperz/PM/DataModel/User.html | 1 + scripts/builder/frontendBuilder.py | 15 +- 30 files changed, 784 insertions(+), 190 deletions(-) create mode 100644 frontend/gamma/js/Clipperz/PM/DataModel/User.AccountInfo.js create mode 100644 frontend/gamma/js/Clipperz/PM/UI/Web/Components/PaymentComponent.js create mode 100644 frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/PaymentController.js diff --git a/.gitignore b/.gitignore index f4556ce..5a2fbbd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ target *.pyc backend/java -scripts/builder/backends/javaBuilder.py \ No newline at end of file +scripts/builder/backends/javaBuilder.py +scripts/btcTranfer +scripts/deltaDeploy \ No newline at end of file diff --git a/frontend/beta/js/Clipperz/Crypto/PRNG.js b/frontend/beta/js/Clipperz/Crypto/PRNG.js index 6fdeca4..92966d0 100644 --- a/frontend/beta/js/Clipperz/Crypto/PRNG.js +++ b/frontend/beta/js/Clipperz/Crypto/PRNG.js @@ -316,9 +316,9 @@ Clipperz.Crypto.PRNG.CryptoRandomRandomnessSource.prototype = MochiKit.Base.upda var bytesToCollect; if (this.boostMode() == true) { - bytesToCollect = 64; - } else { bytesToCollect = 8; + } else { + bytesToCollect = 32; } var randomValuesArray = new Uint8Array(bytesToCollect); diff --git a/frontend/delta/html/index_template.html b/frontend/delta/html/index_template.html index 8ba2715..c9b5130 100644 --- a/frontend/delta/html/index_template.html +++ b/frontend/delta/html/index_template.html @@ -107,7 +107,7 @@ Clipperz_normalizedNewLine = '\x0d\x0a'; /*offline_data_placeholder*/ - + diff --git a/frontend/delta/js/Clipperz/PM/DataModel/EncryptedRemoteObject.js b/frontend/delta/js/Clipperz/PM/DataModel/EncryptedRemoteObject.js index bddc720..b76e4a6 100644 --- a/frontend/delta/js/Clipperz/PM/DataModel/EncryptedRemoteObject.js +++ b/frontend/delta/js/Clipperz/PM/DataModel/EncryptedRemoteObject.js @@ -342,6 +342,7 @@ Clipperz.PM.DataModel.EncryptedRemoteObject.prototype = MochiKit.Base.update(nul var innerDeferredResult; if (this._objectDataStore == null) { +//console.log("EncryptedRemoteObject._getObjectDataStore", this._reference); this._objectDataStore = new Clipperz.KeyValueObjectStore(/*{'name':'EncryptedRemoteObject.objectDataStore [4]'}*/); innerDeferredResult = new Clipperz.Async.Deferred("EncryptedRemoteObject._getObjectDataStore ", {trace:false}); @@ -396,9 +397,10 @@ Clipperz.PM.DataModel.EncryptedRemoteObject.prototype = MochiKit.Base.update(nul var tempObj = this; if (this.isBrandNew()) { -// deferredResult = MochiKit.Async.succeed(true); +//console.log("EncrypedRemoteObject.hasPendingChanges - isBrandNew"); deferredResult = this.hasPendingChangesWhenBrandNew(); } else if (this.hasInitiatedObjectDataStore()) { +//console.log("EncrypedRemoteObject.hasPendingChanges - hasInitiatedObjectDataStore == true"); deferredResult = new Clipperz.Async.Deferred("EncryptedRemoteObject.hasPendingChanges", {trace:false}); deferredResult.collectResults({ 'decryptedData': [ @@ -416,6 +418,7 @@ Clipperz.PM.DataModel.EncryptedRemoteObject.prototype = MochiKit.Base.update(nul }); deferredResult.callback(); } else { +//console.log("EncrypedRemoteObject.hasPendingChanges - hasInitiatedObjectDataStore == false"); deferredResult = MochiKit.Async.succeed(false); } diff --git a/frontend/delta/js/main.js b/frontend/delta/js/main.js index 7f6327d..2ae26ec 100644 --- a/frontend/delta/js/main.js +++ b/frontend/delta/js/main.js @@ -80,7 +80,7 @@ function run () { MochiKit.DOM.addLoadEvent(run); -/* * / +/* */ MochiKit.DOM.addLoadEvent(simulateLogin); function simulateLogin () { var getURLParameter = function (name) { @@ -99,4 +99,4 @@ function simulateLogin () { MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'doLogin', {username:getURLParameter('u'), passphrase:getURLParameter('p')}); } } -/ * */ \ No newline at end of file +/* */ \ No newline at end of file diff --git a/frontend/gamma/html/index_template.html b/frontend/gamma/html/index_template.html index b80a34f..f74d7a3 100644 --- a/frontend/gamma/html/index_template.html +++ b/frontend/gamma/html/index_template.html @@ -52,6 +52,7 @@ Clipperz_normalizedNewLine = '\x0d\x0a'; MochiKit.DOM.addLoadEvent(function () { Clipperz.Crypto.PRNG.defaultRandomGenerator().fastEntropyAccumulationForTestingPurpose(); // MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'doLogin', {username:'joe', passphrase:'clipperz'}); +// MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'doLogin', {username:'j', passphrase:'j'}); }); / * */ diff --git a/frontend/gamma/js/Clipperz/Base.js b/frontend/gamma/js/Clipperz/Base.js index 84b2172..45ceeef 100644 --- a/frontend/gamma/js/Clipperz/Base.js +++ b/frontend/gamma/js/Clipperz/Base.js @@ -61,6 +61,10 @@ MochiKit.Base.update(Clipperz.Base, { return (MochiKit.Base.urlRegExp.test(aValue)); }, +// 'isBitcoin': function (aValue) { +// return (MochiKit.Base.bitcoinRegExp.test(aValue)); +// }, + 'isEmail': function (aValue) { return (MochiKit.Base.emailRegExp.test(aValue)); }, diff --git a/frontend/gamma/js/Clipperz/Crypto/PRNG.js b/frontend/gamma/js/Clipperz/Crypto/PRNG.js index 80d972f..7885429 100644 --- a/frontend/gamma/js/Clipperz/Crypto/PRNG.js +++ b/frontend/gamma/js/Clipperz/Crypto/PRNG.js @@ -318,9 +318,9 @@ Clipperz.Crypto.PRNG.CryptoRandomRandomnessSource.prototype = MochiKit.Base.upda var bytesToCollect; if (this.boostMode() == true) { - bytesToCollect = 64; - } else { bytesToCollect = 8; + } else { + bytesToCollect = 32; } var randomValuesArray = new Uint8Array(bytesToCollect); diff --git a/frontend/gamma/js/Clipperz/Date.js b/frontend/gamma/js/Clipperz/Date.js index 163790e..9c7435d 100644 --- a/frontend/gamma/js/Clipperz/Date.js +++ b/frontend/gamma/js/Clipperz/Date.js @@ -283,6 +283,13 @@ MochiKit.Base.update(Clipperz.Date, { return new Date(Date.parse(aValue)); }, + 'daysBetweendDates': function (date1, date2) { + var ONE_DAY = 24 * 60 * 60 * 1000; + return Math.round(Math.abs(date1.getTime() - date2.getTime()) / ONE_DAY) + }, + + 'distantFuture': 'Mon, 01 January 4001 00:00:00 UTC', + 'distantPast': 'Tue, 04 January 0001 00:00:00 UTC', //========================================================================= 'exception': { diff --git a/frontend/gamma/js/Clipperz/PM/DataModel/Record.Version.Field.js b/frontend/gamma/js/Clipperz/PM/DataModel/Record.Version.Field.js index 986db40..7011cca 100644 --- a/frontend/gamma/js/Clipperz/PM/DataModel/Record.Version.Field.js +++ b/frontend/gamma/js/Clipperz/PM/DataModel/Record.Version.Field.js @@ -105,9 +105,11 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.Record.Version.Field, Object, { if (someValues['isHidden']) { result = 'PASSWORD'; } else if (Clipperz.Base.isUrl(someValues['value'])) { - result = 'URL' + result = 'URL'; +// } else if (Clipperz.Base.isBitcoin(someValues['value'])) { +// result = 'BITCOIN'; } else if (Clipperz.Base.isEmail(someValues['value'])) { - result = 'EMAIL' + result = 'EMAIL'; }; return result; diff --git a/frontend/gamma/js/Clipperz/PM/DataModel/User.AccountInfo.js b/frontend/gamma/js/Clipperz/PM/DataModel/User.AccountInfo.js new file mode 100644 index 0000000..fdd3379 --- /dev/null +++ b/frontend/gamma/js/Clipperz/PM/DataModel/User.AccountInfo.js @@ -0,0 +1,94 @@ +/* + +Copyright 2008-2013 Clipperz Srl + +This file is part of Clipperz, the online password manager. +For further information about its features and functionalities please +refer to http://www.clipperz.com. + +* Clipperz is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + +* Clipperz is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Affero General Public License for more details. + +* You should have received a copy of the GNU Affero General Public + License along with Clipperz. If not, see http://www.gnu.org/licenses/. + +*/ + +Clipperz.PM.DataModel.User.AccountInfo = function(args) { + Clipperz.PM.DataModel.User.AccountInfo.superclass.constructor.apply(this, arguments); + console.log("new AccountInfo", args); + +// { +// "expirationDate": "Sat, 18 January 2014 11:56:17 UTC", +// "featureSet": "EXPIRED", +// "features": [ +// "OFFLINE_COPY", +// "LIST_CARDS" +// ], +// "isExpired": true, +// "isExpiring": false, +// "latestActiveLevel": "TRIAL", +// "latestActiveThreshold": 0.0, +// "paymentVerificationPending": false, +// "payments": [], +// "referenceDate": "Mon, 03 March 2014 09:54:50 UTC" +// } + + this._args = args; + + return this; +} + +//----------------------------------------------------------------------------- + +Clipperz.Base.extend(Clipperz.PM.DataModel.User.AccountInfo, Object, { + + 'toString': function() { + return "Clipperz.PM.DataModel.User.AccountInfo"; + }, + + 'args': function () { + return this._args; + }, + + 'expirationDate': function () { + return Clipperz.PM.Date.parse(this.args()['expirationDate']); + }, + + 'latestActiveLevel': function () { + return this.args()['latestActiveLevel']; + }, + + 'latestActiveThreshold': function () { + return this.args()['latestActiveThreshold']; + }, + + 'status': function () { + return this.args()['featureSet']; + }, + + 'isExpiring': function () { + return this.args()['isExpiring']; + }, + + 'isExpired': function () { + return this.args()['isExpired']; + }, + + 'paymentVerificationPending': function () { + return this.args()['paymentVerificationPending']; + }, + + //========================================================================= + __syntaxFix__: "syntax fix" +}); + +//----------------------------------------------------------------------------- + diff --git a/frontend/gamma/js/Clipperz/PM/DataModel/User.js b/frontend/gamma/js/Clipperz/PM/DataModel/User.js index b94fe4c..ee53e6e 100644 --- a/frontend/gamma/js/Clipperz/PM/DataModel/User.js +++ b/frontend/gamma/js/Clipperz/PM/DataModel/User.js @@ -327,7 +327,7 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User, Object, { var oneTimePasswords; // this.setServerLockValue(someServerData['lock']); - +console.log("USER.unpackServerData", someServerData); headerVersion = this.headerFormatVersion(someServerData['header']); switch (headerVersion) { @@ -410,7 +410,9 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User, Object, { 'recordsIndex': recordsIndex, 'preferences': preferences, 'oneTimePasswords': oneTimePasswords - } + }, +// 'accountInfo': new Clipperz.PM.DataModel.User.AccountInfo(someServerData['accountInfo']), + 'offlineCopyNeeded': someServerData['offlineCopyNeeded'] }; this._serverData = unpackedData; @@ -449,6 +451,11 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User, Object, { return deferredResult; }, + 'resetAllData': function () { + this.deleteAllCleanTextData(); + this._serverData = null; + }, + //------------------------------------------------------------------------- 'connectionVersion': function() { @@ -492,6 +499,13 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User, Object, { ], {trace:false}) }, + 'getCurrentAccountInfo': function () { + return Clipperz.Async.callbacks("User.getHeaderIndex", [ + MochiKit.Base.method(this, 'getServerData'), + MochiKit.Base.itemgetter('accountInfo') + ], {trace:false}) + }, + //========================================================================= 'getRecords': function () { @@ -779,6 +793,20 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User, Object, { return deferredResult; }, + 'deleteAccount': function() { + var deferredResult; + +//MochiKit.Logging.logDebug(">>> user.deleteAccountAction - " + this); + this.deleteAllCleanTextData(); + deferredResult = new Clipperz.Async.Deferred("User.deleteAccount", {trace:false}); + deferredResult.addCallback(MochiKit.Base.method(this.connection(), 'message'), 'deleteUser'); +// deferredResult.addCallback(MochiKit.Base.method(this, 'resetAllLocalData')); + deferredResult.callback(); +//MochiKit.Logging.logDebug("<<< user.deleteAccountAction - " + this); + + return deferredResult; + }, + //========================================================================= __syntaxFix__: "syntax fix" }); diff --git a/frontend/gamma/js/Clipperz/PM/UI/Mobile/Controllers/MainController.js b/frontend/gamma/js/Clipperz/PM/UI/Mobile/Controllers/MainController.js index 245874a..0878699 100644 --- a/frontend/gamma/js/Clipperz/PM/UI/Mobile/Controllers/MainController.js +++ b/frontend/gamma/js/Clipperz/PM/UI/Mobile/Controllers/MainController.js @@ -350,7 +350,7 @@ MochiKit.Base.update(Clipperz.PM.UI.Mobile.Controllers.MainController.prototype, 'selectCardHandler': function (aCardReference) { var deferredResult; - deferredResult = new Clipperz.Async.Deferred("MainController.selectCardHandler", {trace:true}); + deferredResult = new Clipperz.Async.Deferred("MainController.selectCardHandler", {trace:false}); deferredResult.addMethod(this.cardDetail(), 'render'); deferredResult.addMethod(this.user(), 'getRecord', aCardReference); deferredResult.addMethod(this.cardDetail(), 'showCard'); diff --git a/frontend/gamma/js/Clipperz/PM/UI/Web/Components/AccountPanel.js b/frontend/gamma/js/Clipperz/PM/UI/Web/Components/AccountPanel.js index 82c8dfd..11dc56c 100644 --- a/frontend/gamma/js/Clipperz/PM/UI/Web/Components/AccountPanel.js +++ b/frontend/gamma/js/Clipperz/PM/UI/Web/Components/AccountPanel.js @@ -26,6 +26,8 @@ Clipperz.Base.module('Clipperz.PM.UI.Web.Components'); Clipperz.PM.UI.Web.Components.AccountPanel = function(args) { args = args || {}; + this._credentialVefificationFunction = args['credentialVefificationFunction']; + Clipperz.PM.UI.Web.Components.AccountPanel.superclass.constructor.apply(this, arguments); // this._initiallySelectedTab = args.selected || 'ACCOUNT'; @@ -50,6 +52,10 @@ Clipperz.PM.UI.Web.Components.AccountPanel = function(args) { 'LOGIN_HISTORY': { tab: 'loginHistoryTab', panel: 'loginHistoryPanel' + }, + 'DELETE_ACCOUNT': { + tab: 'deleteAccountTab', + panel: 'deleteAccountPanel' } }; @@ -78,7 +84,8 @@ Clipperz.Base.extend(Clipperz.PM.UI.Web.Components.AccountPanel, Clipperz.PM.UI. {tag:'li', id:this.getId('passphraseTab'), children:[{tag:'a', href:'#', html:'Passphrase'}], cls:'first'}, {tag:'li', id:this.getId('OTPTab'), children:[{tag:'a', href:'#', html:'One Time Passwords'}]}, {tag:'li', id:this.getId('preferencesTab'), children:[{tag:'a', href:'#', html:'Preferences'}]}, - {tag:'li', id:this.getId('loginHistoryTab'), children:[{tag:'a', href:'#', html:'Login history'}]} + {tag:'li', id:this.getId('loginHistoryTab'), children:[{tag:'a', href:'#', html:'Login history'}]}, + {tag:'li', id:this.getId('deleteAccountTab'), children:[{tag:'a', href:'#', html:'Delete account'}]} ]} ]} ]}, @@ -130,6 +137,30 @@ Clipperz.Base.extend(Clipperz.PM.UI.Web.Components.AccountPanel, Clipperz.PM.UI. ]}, {tag:'li', id:this.getId('loginHistoryPanel'), children:[ // {tag:'h3', html:"-- Login History --"} + ]}, + {tag:'li', id:this.getId('deleteAccountPanel'), children:[ + {tag:'h3', cls:'deleteAccount', html:"Delete your account"}, + {tag:'form', id:this.getId('deleteAccountForm'), cls:'deleteAccount', children:[ + {tag:'div', cls:'currentCredentials', children:[ + {tag:'div', cls:'field username', children:[ + {tag:'label', html:"username", 'for':this.getId('deleteAccount_currentUsername')}, + {tag:'input', id:this.getId('deleteAccount_currentUsername')} + ]}, + {tag:'div', cls:'field passphrase', children:[ + {tag:'label', html:"passphrase", 'for':this.getId('deleteAccount_currentPassphrase')}, + {tag:'input', type:'password', id:this.getId('deleteAccount_currentPassphrase')} + ]}, + {tag:'div', cls:'confirm', children:[ + {tag:'input', type:'checkbox', id:this.getId('deleteAccount_checkbox')}, + {tag:'label', html:"I understand that all my data will be deleted and that this action is irreversible", 'for':this.getId('deleteAccount_checkbox')} + ]} + ]} + ]}, + {tag:'div', cls:'clear'}, + {tag:'div', cls:'confirmButton', id:this.getId('confirmationButton'), children:[ + {tag:'a', id:this.getId('deleteAccountButton'), href:'#', html:"Delete my account", cls:'deleteAccountButton disabled'} + ]} + ]} ]} ]} @@ -139,10 +170,58 @@ Clipperz.Base.extend(Clipperz.PM.UI.Web.Components.AccountPanel, Clipperz.PM.UI. ]); this.tabPanelController().setup({selected:this.initiallySelectedTab()}); + MochiKit.Signal.connect(this.getId('deleteAccountButton'), 'onclick', this, 'deleteAccount'); + + MochiKit.Signal.connect(this.getId('deleteAccount_currentUsername'), 'onchange', this, 'deleteAccountFormChangedValue'); + MochiKit.Signal.connect(this.getId('deleteAccount_currentUsername'), 'onkeyup', this, 'deleteAccountFormChangedValue'); + MochiKit.Signal.connect(this.getId('deleteAccount_currentPassphrase'), 'onchange', this, 'deleteAccountFormChangedValue'); + MochiKit.Signal.connect(this.getId('deleteAccount_currentPassphrase'), 'onkeyup', this, 'deleteAccountFormChangedValue'); + MochiKit.Signal.connect(this.getId('deleteAccount_checkbox'), 'onchange', this, 'deleteAccountFormChangedValue'); }, //------------------------------------------------------------------------- + 'deleteAccount': function (anEvent) { +console.log("DELETE ACCOUNT"); + + anEvent.preventDefault(); + MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'deleteAccount', this.deleteAccountCredentials()); + }, + + 'deleteAccountCredentials': function () { + return { + username: this.getElement('deleteAccount_currentUsername').value, + passphrase: this.getElement('deleteAccount_currentPassphrase').value + }; + }, + + 'deleteAccountFormChangedValue': function (anEvent) { + anEvent.preventDefault(); + + if (this.verifyDeleteAccountCredentials()) { + MochiKit.DOM.removeElementClass(this.getElement('deleteAccountButton'), 'disabled'); + } else { + MochiKit.DOM.addElementClass(this.getElement('deleteAccountButton'), 'disabled') + } + }, + + 'verifyDeleteAccountCredentials': function () { + var result; + var credentials; + var checkboxChecked; + + result = false; + checkboxChecked = this.getElement('deleteAccount_checkbox').checked; + + if (checkboxChecked) { + result = this._credentialVefificationFunction(this.deleteAccountCredentials()); + } + + return result; + }, + + //------------------------------------------------------------------------- + __syntaxFix__: "syntax fix" }); diff --git a/frontend/gamma/js/Clipperz/PM/UI/Web/Components/CardDialogRecordFieldComponent.js b/frontend/gamma/js/Clipperz/PM/UI/Web/Components/CardDialogRecordFieldComponent.js index 689406a..dd0688f 100644 --- a/frontend/gamma/js/Clipperz/PM/UI/Web/Components/CardDialogRecordFieldComponent.js +++ b/frontend/gamma/js/Clipperz/PM/UI/Web/Components/CardDialogRecordFieldComponent.js @@ -132,6 +132,10 @@ Clipperz.Base.extend(Clipperz.PM.UI.Web.Components.CardDialogRecordFieldComponen MochiKit.Style.showElement(this.getId('actionLink')); MochiKit.DOM.setElementClass(this.getId('actionLink'), 'url'); break; + case 'BITCOIN': + MochiKit.Style.showElement(this.getId('actionLink')); + MochiKit.DOM.setElementClass(this.getId('actionLink'), 'url'); + break; case 'EMAIL': MochiKit.Style.showElement(this.getId('actionLink')); MochiKit.DOM.setElementClass(this.getId('actionLink'), 'email'); diff --git a/frontend/gamma/js/Clipperz/PM/UI/Web/Components/LoginForm.js b/frontend/gamma/js/Clipperz/PM/UI/Web/Components/LoginForm.js index 38a9421..f0e721a 100644 --- a/frontend/gamma/js/Clipperz/PM/UI/Web/Components/LoginForm.js +++ b/frontend/gamma/js/Clipperz/PM/UI/Web/Components/LoginForm.js @@ -144,24 +144,16 @@ Clipperz.Base.extend(Clipperz.PM.UI.Web.Components.LoginForm, Clipperz.PM.UI.Com //------------------------------------------------------------------------- 'loginEventHandler': function(anEvent) { -// var username; -// var passphrase; - var signalArguments; + var credentials; anEvent.preventDefault(); -// username = this.getElement('usernameField').value; -// passphrase = this.getElement('passphraseField').value; - -// signalArguments = {username:username}; -// signalArguments.passphrase = passphrase; - - signalArguments = { + credentials = { 'username': this.getElement('usernameField').value, 'passphrase': this.getElement('passphraseField').value }; - MochiKit.Signal.signal(this, 'doLogin', signalArguments); + MochiKit.Signal.signal(this, 'doLogin', credentials); }, //------------------------------------------------------------------------- diff --git a/frontend/gamma/js/Clipperz/PM/UI/Web/Components/PaymentComponent.js b/frontend/gamma/js/Clipperz/PM/UI/Web/Components/PaymentComponent.js new file mode 100644 index 0000000..8e2cd76 --- /dev/null +++ b/frontend/gamma/js/Clipperz/PM/UI/Web/Components/PaymentComponent.js @@ -0,0 +1,220 @@ +/* + +Copyright 2008-2013 Clipperz Srl + +This file is part of Clipperz, the online password manager. +For further information about its features and functionalities please +refer to http://www.clipperz.com. + +* Clipperz is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + +* Clipperz is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Affero General Public License for more details. + +* You should have received a copy of the GNU Affero General Public + License along with Clipperz. If not, see http://www.gnu.org/licenses/. + +*/ + +Clipperz.Base.module('Clipperz.PM.UI.Web.Components'); + +Clipperz.PM.UI.Web.Components.PaymentComponent = function(args) { + args = args || {}; + + Clipperz.PM.UI.Web.Components.PaymentComponent.superclass.constructor.apply(this, arguments); + + this._subscriptionOptions = null; + this._currencies = null; + this._selectedCurrency = 'mBTC'; + this._selectedOption = 'FAN'; + +// this._displayMode = 'fixed'; // 'scrollable'; + + return this; +} + +//============================================================================= + +Clipperz.Base.extend(Clipperz.PM.UI.Web.Components.PaymentComponent, Clipperz.PM.UI.Common.Components.BaseComponent, { + + //------------------------------------------------------------------------- + + 'toString': function () { + return "Clipperz.PM.UI.Web.Components.PaymentComponent component"; + }, + + //------------------------------------------------------------------------- + + 'subscriptionOptions': function () { + return this._subscriptionOptions; + }, + + 'setSubscriptionOptions': function (someSubscriptionOptions) { + this._subscriptionOptions = someSubscriptionOptions['options']; + this._currencies = MochiKit.Base.keys(MochiKit.Base.values(MochiKit.Base.values(someSubscriptionOptions['options'])[0])[0]['value']); + if (typeof(someSubscriptionOptions['latestActiveLevel']) != 'undefined') { + this._selectedOption = someSubscriptionOptions['latestActiveLevel']; + } + + this.renderSubscriptionOptions(this._subscriptionOptions); + }, + + //............................................................................ + + 'currencies': function () { + return this._currencies; + }, + + 'selectedCurrency': function () { + return this._selectedCurrency; + }, + + 'setSelectedCurrency': function (aValue) { + this._selectedCurrency = aValue; + }, + + 'setSelectedCurrencyIfNull': function (aValue) { + if (this._selectedCurrency == null) { + this._selectedCurrency = aValue; + } + }, + + //............................................................................ + + 'selectedOption': function () { + return this._selectedOption; + }, + + 'setSelectedOption': function (aValue) { + this._selectedOption = aValue; + }, + + //------------------------------------------------------------------------- + + 'renderSelf': function () { + this.append(this.element(), {tag:'div', cls:'PaymentDialog loading', id:this.getId('panel'), children: [ + {tag:'div', id:this.getId('subscriptions'), cls:'subscriptions'}, + {tag:'div', cls:'footer', children:[ + {tag:'div', id:this.getId('cancelButton'), cls:'button cancel', html:"cancel"}, + {tag:'div', id:this.getId('payButton'), cls:'button pay', html:"pay"} + ]} + ]}); + + MochiKit.Signal.connect(this.getElement('cancelButton'), 'onclick', this, 'handleCancel'); + MochiKit.Signal.connect(this.getElement('payButton'), 'onclick', this, 'handlePayButtonClick'); + }, + + //------------------------------------------------------------------------- + + 'priceOptionComponent': function (aCurrency, aSelectedOption, aSubscriptionInfo) { + var isSelected = (aSubscriptionInfo['code'] == aSelectedOption); + + return {tag:'li', 'data-type':'option', 'data-code':aSubscriptionInfo['code'], cls:isSelected ? 'selected' : '', children:[ + {tag:'h3', html:aSubscriptionInfo['name']}, + {tag:'h5', cls:'currency', html:aCurrency}, + {tag:'h5', cls:'value', html:aSubscriptionInfo['value'][aCurrency]} + ]}; + }, + + 'optionComparator': function (aOption, bOption) { + return MochiKit.Base.compare(aOption['CLZ'], bOption['CLZ']); + }, + + 'renderCurrency': function (aSelectedCurrency, aCurrency) { + return {tag:'li', 'data-type':'currency', 'data-code':aCurrency, cls:aCurrency == aSelectedCurrency ? 'selected' : '', html:aCurrency} + }, + + 'allSubscriptionOptions': function () { + return MochiKit.Selector.findChildElements(this.getElement('subscriptions'), ["div.options li"]); + }, + + 'allCurrencyOptions': function () { + return MochiKit.Selector.findChildElements(this.getElement('subscriptions'), ["ul.currencies li"]); + }, + + 'renderSubscriptionOptions': function (someSubscriptionOptions, overwrite) { + var currentCurrency = this.selectedCurrency(); + var currencyRenderer = MochiKit.Base.partial(this.renderCurrency, this.selectedCurrency()) + var subscriptionOptionRenderer = MochiKit.Base.partial(this.priceOptionComponent, this.selectedCurrency(), this.selectedOption()); + var self = this; + + if (overwrite) { + MochiKit.Base.map(MochiKit.Signal.disconnectAll, this.allCurrencyOptions()); + MochiKit.Base.map(MochiKit.Signal.disconnectAll, this.allSubscriptionOptions()); + this.getElement('subscriptions').innerHTML = ''; + } + + this.append(this.getElement('subscriptions'), {tag:'ul', cls:'currencies', children:MochiKit.Base.map(currencyRenderer, this.currencies())}); + + this.append(this.getElement('subscriptions'), {tag:'div', cls:'options', children:[ + {tag:'div', cls:'yearly', children:[ + {tag:'h1', html:"Yearly"}, + {tag:'ul', children:MochiKit.Base.map(subscriptionOptionRenderer, MochiKit.Base.values(someSubscriptionOptions['P1Y']).sort(this.optionComparator))} + ]}, + {tag:'div', cls:'perpetual', children:[ + {tag:'h1', html:"Perpetual"}, + {tag:'ul', children:MochiKit.Base.map(subscriptionOptionRenderer, MochiKit.Base.values(someSubscriptionOptions['--']).sort(this.optionComparator))} + ]} + ]}); + + MochiKit.Base.map(function (aLi) { MochiKit.Signal.connect(aLi, 'onclick', self, 'handleChangeCurrencySelection') }, this.allCurrencyOptions()); + MochiKit.Base.map(function (aLi) { MochiKit.Signal.connect(aLi, 'onclick', self, 'handleChangeOptionSelection') }, this.allSubscriptionOptions()); + }, + + //------------------------------------------------------------------------- + + 'handleChangeOptionSelection': function (anEvent) { + var code = MochiKit.DOM.getNodeAttribute(anEvent.src(), 'data-code'); + + if (code != this.selectedOption()) { + MochiKit.Base.map(function (aLi) { MochiKit.DOM.removeElementClass(aLi, 'selected') }, this.allSubscriptionOptions()); + MochiKit.DOM.addElementClass(anEvent.src(), 'selected'); + this.setSelectedOption(code); + } + }, + + 'handleChangeCurrencySelection': function (anEvent) { + var code = MochiKit.DOM.getNodeAttribute(anEvent.src(), 'data-code'); + + if (code != this.selectedCurrency()) { + MochiKit.Base.map(function (aLi) { MochiKit.DOM.removeElementClass(aLi, 'selected') }, this.allCurrencyOptions()); + MochiKit.DOM.addElementClass(anEvent.src(), 'selected'); + this.setSelectedCurrency(code); + this.renderSubscriptionOptions(this.subscriptionOptions(), true); + } + }, + + 'handlePayButtonClick': function (anEvent) { + console.log("PAY: ", this.selectedOption(), this.selectedCurrency()); + MochiKit.Signal.signal(this, 'pay', {currency:this.selectedCurrency(), type:this.selectedOption()}); + }, + + 'handleCancel': function (anEvent) { +console.log("CANCEL"); + MochiKit.Signal.signal(this, 'cancel'); + }, + +/* + 'displayMode': function () { + return this._displayMode; + }, + + 'setDisplayMode': function (aValue) { + this._displayMode = aValue; + }, +*/ + + //========================================================================= + + 'showQrCode': function (someParameters) { +console.log("SHOW QR CODE", someParameters); + }, + + //========================================================================= + __syntaxFix__: "syntax fix" +}); diff --git a/frontend/gamma/js/Clipperz/PM/UI/Web/Components/UserInfoBox.js b/frontend/gamma/js/Clipperz/PM/UI/Web/Components/UserInfoBox.js index 91085cf..d2cefeb 100644 --- a/frontend/gamma/js/Clipperz/PM/UI/Web/Components/UserInfoBox.js +++ b/frontend/gamma/js/Clipperz/PM/UI/Web/Components/UserInfoBox.js @@ -110,7 +110,6 @@ Clipperz.Base.extend(Clipperz.PM.UI.Web.Components.UserInfoBox, Clipperz.PM.UI.C deferredResult = Clipperz.Async.callbacks("UserInfoBox.unlock", [ MochiKit.Base.partial(Clipperz.Visual.deferredAnimation, MochiKit.Visual.fade, maskElement, {from:0.75, to:0.0, duration:0.5}), -// Clipperz.Visual.deferredAnimation(MochiKit.Visual.fade, maskElement, {from:0.75, to:0.0, duration:0.5}), MochiKit.Base.partial(MochiKit.DOM.removeElementClass, this.element(), 'locked') ], {trace:false}); }, @@ -119,16 +118,7 @@ Clipperz.Base.extend(Clipperz.PM.UI.Web.Components.UserInfoBox, Clipperz.PM.UI.C 'askForPassphrase': function () { var unlockPasswordComponent; -/* - var deferredResult; - - deferredResult = new Clipperz.Async.Deferred("UserInfoBox.askForPassphrase", {trace:false}); - deferredResult.addCallback(MochiKit.Async.succeed, 'test'); - - deferredResult.callback(); - - return deferredResult; -*/ + unlockPasswordComponent = new Clipperz.PM.UI.Web.Components.UnlockPasswordComponent({ 'title': "Unlock account", 'text': "Insert the passprase to unlock the account", @@ -166,9 +156,12 @@ Clipperz.Base.extend(Clipperz.PM.UI.Web.Components.UserInfoBox, Clipperz.PM.UI.C {tag:'span', id:this.getId('directLoginsLabel'), html:"direct logins"} ]} ]}, +// {tag:'div', cls:'accountInfo', id:this.getId('accountInfo'), children:[ +// {tag:'h5', html:"Account info"}, +// ]}, {tag:'div', cls:'accountInfo', children:[ {tag:'div', cls:'payButton', children:[ - {tag:'a', href:'#', id:this.getId('payButton'), cls:'info', html:"info"} + {tag:'a', href:'#', id:this.getId('infoButton'), cls:'info', html:"info"} ]}, {tag:'h5', html:"Account info"}, {tag:'div', cls:'accountStatus', children:[ @@ -177,12 +170,10 @@ Clipperz.Base.extend(Clipperz.PM.UI.Web.Components.UserInfoBox, Clipperz.PM.UI.C ]}, {tag:'div', cls:'accountLevel', children:[ {tag:'span', cls:'label', html:"level"}, -// {tag:'span', cls:'level', html:"★☆☆☆"} {tag:'span', cls:'level', html:"☆☆☆☆"} ]}, {tag:'div', cls:'accountExpiration', children:[ {tag:'span', cls:'label', html:"expires"}, -// {tag:'span', cls:'expriation', html:"on 26 April 2014"} {tag:'span', cls:'expriation', html:"never"} ]} ]}, @@ -193,7 +184,7 @@ Clipperz.Base.extend(Clipperz.PM.UI.Web.Components.UserInfoBox, Clipperz.PM.UI.C MochiKit.Signal.connect(this.getElement('logout'), 'onclick', this, 'handleLogout'); MochiKit.Signal.connect(this.getElement('lock'), 'onclick', this, 'toggleLock'); - MochiKit.Signal.connect(this.getElement('payButton'), 'onclick', this, 'handlePayButton'); + MochiKit.Signal.connect(this.getElement('infoButton'), 'onclick', this, 'handleInfoButton'); this._lockTooltip = new Clipperz.PM.UI.Common.Components.Tooltip({ element: this.getElement('lock'), @@ -207,149 +198,21 @@ Clipperz.Base.extend(Clipperz.PM.UI.Web.Components.UserInfoBox, Clipperz.PM.UI.C ]} ); MochiKit.Style.hideElement(this.getId('modalDialogMask')); - -// this.drawUserInfoBackground(this.getElement('canvas')); }, //------------------------------------------------------------------------- - 'handlePayButton': function (anEvent) { + 'handleInfoButton': function (anEvent) { anEvent.preventDefault(); window.open('https://www.clipperz.com/pricing/', '_blank'); }, - //------------------------------------------------------------------------- -/* - 'drawUserInfoBackground': function (canvas) { - var kMyDrawingFunctionWidth = 188.0; - var kMyDrawingFunctionHeight = 154.0; - - var context = canvas.getContext("2d"); - var color; - var resolution; - var alignStroke; - var path; - var pointX; - var pointY; - var controlPoint1X; - var controlPoint1Y; - var controlPoint2X; - var controlPoint2Y; - var gradient; - if (window.devicePixelRatio) - resolution = window.devicePixelRatio; - else - resolution = 1.0; - resolution *= 0.5 * (canvas.width / kMyDrawingFunctionWidth + canvas.height / kMyDrawingFunctionHeight); - - context.save(); - context.scale(canvas.width / kMyDrawingFunctionWidth, canvas.height / kMyDrawingFunctionHeight); - context.clearRect(0.0, 0.0, kMyDrawingFunctionWidth, kMyDrawingFunctionHeight); - - // Setup for Shadow Effect - color = "rgba(0.0%, 0.0%, 0.0%, 0.667)"; - context.save(); - context.shadowColor = color; - context.shadowBlur = 3.0; - context.shadowOffsetX = 5.729 * Math.cos(7.592) * resolution; - context.shadowOffsetY = 5.729 * Math.sin(7.592) * resolution; - - // Layer 1 - - alignStroke = 0.0; - context.beginPath(); - pointX = 169.5; - pointY = 141.5; - pointX = (Math.round(resolution * pointX + alignStroke) - alignStroke) / resolution; - pointY = (Math.round(resolution * pointY + alignStroke) - alignStroke) / resolution; - context.moveTo(pointX, pointY); - pointX = 177.5; - pointY = 133.5; - pointX = (Math.round(resolution * pointX + alignStroke) - alignStroke) / resolution; - pointY = (Math.round(resolution * pointY + alignStroke) - alignStroke) / resolution; - controlPoint1X = 173.889; - controlPoint1Y = 141.5; - controlPoint1X = (Math.round(resolution * controlPoint1X + alignStroke) - alignStroke) / resolution; - controlPoint1Y = (Math.round(resolution * controlPoint1Y + alignStroke) - alignStroke) / resolution; - controlPoint2X = 177.5; - controlPoint2Y = 137.889; - controlPoint2X = (Math.round(resolution * controlPoint2X + alignStroke) - alignStroke) / resolution; - controlPoint2Y = (Math.round(resolution * controlPoint2Y + alignStroke) - alignStroke) / resolution; - context.bezierCurveTo(controlPoint1X, controlPoint1Y, controlPoint2X, controlPoint2Y, pointX, pointY); - pointX = 177.5; - pointY = 19.5; - pointX = (Math.round(resolution * pointX + alignStroke) - alignStroke) / resolution; - pointY = (Math.round(resolution * pointY + alignStroke) - alignStroke) / resolution; - context.lineTo(pointX, pointY); - pointX = 169.5; - pointY = 11.5; - pointX = (Math.round(resolution * pointX + alignStroke) - alignStroke) / resolution; - pointY = (Math.round(resolution * pointY + alignStroke) - alignStroke) / resolution; - controlPoint1X = 177.5; - controlPoint1Y = 15.111; - controlPoint1X = (Math.round(resolution * controlPoint1X + alignStroke) - alignStroke) / resolution; - controlPoint1Y = (Math.round(resolution * controlPoint1Y + alignStroke) - alignStroke) / resolution; - controlPoint2X = 173.889; - controlPoint2Y = 11.5; - controlPoint2X = (Math.round(resolution * controlPoint2X + alignStroke) - alignStroke) / resolution; - controlPoint2Y = (Math.round(resolution * controlPoint2Y + alignStroke) - alignStroke) / resolution; - context.bezierCurveTo(controlPoint1X, controlPoint1Y, controlPoint2X, controlPoint2Y, pointX, pointY); - pointX = 18.5; - pointY = 11.5; - pointX = (Math.round(resolution * pointX + alignStroke) - alignStroke) / resolution; - pointY = (Math.round(resolution * pointY + alignStroke) - alignStroke) / resolution; - context.lineTo(pointX, pointY); - pointX = 10.5; - pointY = 19.5; - pointX = (Math.round(resolution * pointX + alignStroke) - alignStroke) / resolution; - pointY = (Math.round(resolution * pointY + alignStroke) - alignStroke) / resolution; - controlPoint1X = 14.111; - controlPoint1Y = 11.5; - controlPoint1X = (Math.round(resolution * controlPoint1X + alignStroke) - alignStroke) / resolution; - controlPoint1Y = (Math.round(resolution * controlPoint1Y + alignStroke) - alignStroke) / resolution; - controlPoint2X = 10.5; - controlPoint2Y = 15.111; - controlPoint2X = (Math.round(resolution * controlPoint2X + alignStroke) - alignStroke) / resolution; - controlPoint2Y = (Math.round(resolution * controlPoint2Y + alignStroke) - alignStroke) / resolution; - context.bezierCurveTo(controlPoint1X, controlPoint1Y, controlPoint2X, controlPoint2Y, pointX, pointY); - pointX = 10.5; - pointY = 133.5; - pointX = (Math.round(resolution * pointX + alignStroke) - alignStroke) / resolution; - pointY = (Math.round(resolution * pointY + alignStroke) - alignStroke) / resolution; - context.lineTo(pointX, pointY); - pointX = 18.5; - pointY = 141.5; - pointX = (Math.round(resolution * pointX + alignStroke) - alignStroke) / resolution; - pointY = (Math.round(resolution * pointY + alignStroke) - alignStroke) / resolution; - controlPoint1X = 10.5; - controlPoint1Y = 137.889; - controlPoint1X = (Math.round(resolution * controlPoint1X + alignStroke) - alignStroke) / resolution; - controlPoint1Y = (Math.round(resolution * controlPoint1Y + alignStroke) - alignStroke) / resolution; - controlPoint2X = 14.111; - controlPoint2Y = 141.5; - controlPoint2X = (Math.round(resolution * controlPoint2X + alignStroke) - alignStroke) / resolution; - controlPoint2Y = (Math.round(resolution * controlPoint2Y + alignStroke) - alignStroke) / resolution; - context.bezierCurveTo(controlPoint1X, controlPoint1Y, controlPoint2X, controlPoint2Y, pointX, pointY); - pointX = 169.5; - pointY = 141.5; - pointX = (Math.round(resolution * pointX + alignStroke) - alignStroke) / resolution; - pointY = (Math.round(resolution * pointY + alignStroke) - alignStroke) / resolution; - context.lineTo(pointX, pointY); - context.closePath(); - gradient = context.createLinearGradient(94.0, 11.5, 94.0, 141.5); - color = "#EE9B69"; - gradient.addColorStop(0.0, color); - color = "#E38D62"; - gradient.addColorStop(1.0, color); - context.fillStyle = gradient; - context.fill(); - - // Shadow Effect - context.restore(); - - context.restore(); + 'handlePayButton': function (anEvent) { + anEvent.preventDefault(); + MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'makePayment', anEvent); }, -*/ + + //------------------------------------------------------------------------- 'updateUserDetails': function (someUserInfo) { @@ -360,6 +223,103 @@ Clipperz.Base.extend(Clipperz.PM.UI.Web.Components.UserInfoBox, Clipperz.PM.UI.C } }, + 'numberOfStarsMatchingActiveLevel': function (aValue) { + var maxLevel = 15; + var value; + var result; + + value = Math.min(aValue, maxLevel); + result = value / maxLevel * 5; + + return result; + }, + + 'starsLabel': function(numberOfActiveStars) { + var result; + var i; + + // "★☆☆☆" + result = ""; + for (i=0; i<5; i++) { + if (i < numberOfActiveStars) { + result = result + "★"; + } else { + result = result + "☆"; + } + } + + return result; + }, +/* + 'updateCurrentSubscriptionDetails': function (anAccountInfo) { +//console.log("AccountInfo", anAccountInfo); + var subscriptionLevel = anAccountInfo.latestActiveLevel(); + + var expireLabel; + var formattedDate; + + if (anAccountInfo.expirationDate() == Clipperz.Date.distantFuture) { + formattedDate = "never"; + } else { + formattedDate = Clipperz.PM.Date.formatDateWithTemplate(anAccountInfo.expirationDate(), "D, d M Y"); + } + + this.append(this.getElement('accountInfo'), [ + {tag:'div', cls:'accountStatus', children:[ + {tag:'span', cls:'label', html:"status"}, + {tag:'span', cls:'status', html:anAccountInfo.status()} + ]} + ]); + + if (anAccountInfo.isExpired()) { + expireLabel = "expired"; + } else { + expireLabel = "expires"; + } + + this.append(this.getElement('accountInfo'), [ + + {tag:'div', cls:'accountLevel', children:[ + {tag:'span', cls:'label', html:"level"}, + {tag:'span', cls:'level', html:this.starsLabel(this.numberOfStarsMatchingActiveLevel(anAccountInfo.latestActiveThreshold()))} + ]}, + + {tag:'div', cls:'accountExpiration', children:[ + {tag:'span', cls:'label', html:expireLabel}, + {tag:'span', cls:'expriation', html:formattedDate} + ]} + ]); + + if (anAccountInfo.isExpired() || anAccountInfo.isExpiring()) { + var buttonLabel; + + if (anAccountInfo.paymentVerificationPending()) { + buttonLabel = "Verify payment"; + } else { + if (subscriptionLevel == 'TRIAL') { + buttonLabel = "Subscribe"; + } else if (subscriptionLevel == 'EARLY_ADOPTER') { + buttonLabel = "Donate"; + } else if (subscriptionLevel == 'PATRON') { + buttonLabel = "Donate"; + } else if (subscriptionLevel == 'PAYMENT_PENDING') { + buttonLabel = "Verify payment"; + } else { + buttonLabel = "Renew subscription"; + } + } + + this.append(this.getElement('accountInfo'), [ + {tag:'div', cls:'payButton', children:[ + {tag:'a', href:'#', id:this.getId('payButton'), cls:'info', html:buttonLabel} + ]}, + ]); + + MochiKit.Signal.connect(this.getElement('payButton'), 'onclick', this, 'handlePayButton'); + + } + }, +*/ //------------------------------------------------------------------------- __syntaxFix__: "syntax fix" }); diff --git a/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/AppController.js b/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/AppController.js index 1448dee..4d99f7e 100644 --- a/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/AppController.js +++ b/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/AppController.js @@ -49,6 +49,8 @@ Clipperz.PM.UI.Web.Controllers.AppController = function(args) { // MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, 'deleteCard', this, 'handleDeleteCard'); MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, 'userDataSuccessfullySaved', this, 'userDataSuccessfullySavedHandler'); +// MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, 'makePayment', this, 'handlePaymentRequest'); + MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, 'deleteAccount', this, 'deleteAccount'); return this; } @@ -125,7 +127,7 @@ MochiKit.Base.update(Clipperz.PM.UI.Web.Controllers.AppController.prototype, { 'accountPanel': function () { if (this._accountPanel == null) { - this._accountPanel = new Clipperz.PM.UI.Web.Components.AccountPanel(/*{selected:'Preferences'}*/); + this._accountPanel = new Clipperz.PM.UI.Web.Components.AccountPanel({credentialVefificationFunction: MochiKit.Base.bind(this.credentialVefificationFunction, this) /*, selected:'Preferences'*/}); } return this._accountPanel; @@ -199,6 +201,10 @@ MochiKit.Base.update(Clipperz.PM.UI.Web.Controllers.AppController.prototype, { ] }) deferredResult.addMethod(this.userInfoBox(), 'updateUserDetails'); + + deferredResult.addMethod(this.user(), 'getCurrentAccountInfo'); +// deferredResult.addMethod(this.userInfoBox(), 'updateCurrentSubscriptionDetails'); + deferredResult.callback(this.user()); return deferredResult; @@ -343,6 +349,64 @@ MochiKit.Base.update(Clipperz.PM.UI.Web.Controllers.AppController.prototype, { } }, + //============================================================================= +/* + 'handlePaymentRequest': function (anEvent) { + var deferredResult; + var paymentController; + +console.log("AppController - handlePaymentRequest", anEvent); + paymentController = new Clipperz.PM.UI.Web.Controllers.PaymentController({delegate:this}); + deferredResult = paymentController.run(anEvent.src()); + + return deferredResult; + }, + + 'subscriptionOptions': function () { + return this.user().connection().message('subscriptionOptions'); + }, + + 'getPaymentSubscriptionInfo': function () { + return this.user().connection().message('paymentRequest'); + }, + + 'getPaymentAddress': function (aCurrency, aLevel, aSubscription) { + return this.user().connection().message('paymentAddress', { subscription:aSubscription, currency:aCurrency, level:aLevel }); + }, +*/ + //============================================================================= + + 'credentialVefificationFunction': function (someCredentials) { + var result; + var deferredPassphrase; + + result = false; + + deferredPassphrase = this.user().getPassphrase(); + if (deferredPassphrase.state() == 'success') { + result = (someCredentials['passphrase'] == deferredPassphrase.results[0]); + } + + result = result && (someCredentials['username'] == this.user().username()); + + return result; + }, + + 'deleteAccount': function (someCredentials) { + if (this.credentialVefificationFunction(someCredentials)) { + var deferredResult; + + deferredResult = new Clipperz.Async.Deferred("AppController.deleteAccount", {trace:false}); + deferredResult.addMethod(this.user(), 'deleteAccount'); + deferredResult.addCallback(MochiKit.Signal.signal, this, 'logout'); + deferredResult.addErrback(function (anError) { + console.log("ERROR", anError); + }); + + deferredResult.callback(); + } + }, + //============================================================================= __syntaxFix__: "syntax fix" }); diff --git a/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/CardDialogController.js b/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/CardDialogController.js index b1ff81f..caf68bf 100644 --- a/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/CardDialogController.js +++ b/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/CardDialogController.js @@ -394,6 +394,9 @@ Clipperz.Base.extend(Clipperz.PM.UI.Web.Controllers.CardDialogController, Object window.open(url); break; + case 'BITCOIN': + window.open(someValues['value']); + break; case 'EMAIL': var url; diff --git a/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/MainController.js b/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/MainController.js index 9194125..c98a0e1 100644 --- a/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/MainController.js +++ b/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/MainController.js @@ -190,7 +190,7 @@ MochiKit.Base.update(Clipperz.PM.UI.Web.Controllers.MainController.prototype, { //----------------------------------------------------------------------------- 'handleLogout': function(anEvent) { - this.exit('logout.html'); + this.exit('exit.html'); }, //----------------------------------------------------------------------------- diff --git a/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/NewUserWizardController.js b/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/NewUserWizardController.js index b70aa17..c008935 100644 --- a/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/NewUserWizardController.js +++ b/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/NewUserWizardController.js @@ -320,6 +320,7 @@ MochiKit.Base.update(Clipperz.PM.UI.Web.Controllers.NewUserWizardController.prot 'done': function () { this.doneWithRuler(); + this.user().resetAllData(); MochiKit.Signal.signal(this, 'done', {'user': this.user()}); }, diff --git a/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/PaymentController.js b/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/PaymentController.js new file mode 100644 index 0000000..f6b84fc --- /dev/null +++ b/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/PaymentController.js @@ -0,0 +1,111 @@ +/* + +Copyright 2008-2013 Clipperz Srl + +This file is part of Clipperz, the online password manager. +For further information about its features and functionalities please +refer to http://www.clipperz.com. + +* Clipperz is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + +* Clipperz is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Affero General Public License for more details. + +* You should have received a copy of the GNU Affero General Public + License along with Clipperz. If not, see http://www.gnu.org/licenses/. + +*/ + +Clipperz.Base.module('Clipperz.PM.UI.Web.Controllers'); + +Clipperz.PM.UI.Web.Controllers.PaymentController = function(args) { + Clipperz.PM.UI.Web.Controllers.PaymentController.superclass.constructor.apply(this, arguments); + + this._delegate = args['delegate']; + this._referenceElement = null; + this._paymentComponent = null; + + return this; +} + +//MochiKit.Base.update(Clipperz.PM.UI.Web.Controllers.AppController.prototype, { +Clipperz.Base.extend(Clipperz.PM.UI.Web.Controllers.PaymentController, Object, { + + 'toString': function() { + return "Clipperz.PM.UI.Web.Controllers.PaymentController"; + }, + + 'delegate': function () { + return this._delegate; + }, + + //------------------------------------------------------------------------- + + 'referenceElement': function () { + return this._referenceElement; + }, + + 'setReferenceElement': function (anElement) { + this._referenceElement = anElement; + }, + + //------------------------------------------------------------------------- + + 'paymentComponent': function () { + if (this._paymentComponent == null) { + var paymentComponent = new Clipperz.PM.UI.Web.Components.PaymentComponent(); + + MochiKit.Signal.connect(paymentComponent, 'cancel', this, 'handleCancel'); + MochiKit.Signal.connect(paymentComponent, 'pay', this, 'handlePaymentRequest'); + + this._paymentComponent = paymentComponent; + } + + return this._paymentComponent; + }, + + //------------------------------------------------------------------------- + + 'run': function (anElement) { + var deferredResult; + + this.setReferenceElement(anElement); + + deferredResult = new Clipperz.Async.Deferred("PaymentController.run", {trace:false}); + deferredResult.addMethod(this.paymentComponent(), 'deferredShowModal', {openFromElement:this.referenceElement()}); + deferredResult.addMethod(this.delegate(), 'subscriptionOptions'); + deferredResult.addMethod(this.paymentComponent(), 'setSubscriptionOptions'); + deferredResult.callback(); + + return deferredResult; + }, + + //============================================================================= + + 'handlePaymentRequest': function (someOptions) { +console.log("PaymentController - handlePaymentRequest", someOptions['currency'], someOptions['type']); + var deferredResult; + + deferredResult = new Clipperz.Async.Deferred("PaymentController.handlePaymentRequest", {trace:false}); + deferredResult.addMethod(this.delegate(), 'getPaymentSubscriptionInfo'); + deferredResult.addCallback(function (subscriptionOptions) { return subscriptionOptions['subscription']}); + deferredResult.addMethod(this.delegate(), 'getPaymentAddress', someOptions['currency'], someOptions['type']); + deferredResult.addMethod(this.paymentComponent(), 'showQrCode'); +// deferredResult.addCallback(function (subscriptionInfo) { console.log("SUBSCRIPTION INFO", subscriptionInfo); }); + deferredResult.callback(); + + return deferredResult; + }, + + 'handleCancel': function (anEvent) { +console.log("PaymentController - handleCancel"); + }, + + //============================================================================= + __syntaxFix__: "syntax fix" +}); diff --git a/frontend/gamma/properties/gamma.properties.json b/frontend/gamma/properties/gamma.properties.json index 1bc9e27..9dd9fe5 100644 --- a/frontend/gamma/properties/gamma.properties.json +++ b/frontend/gamma/properties/gamma.properties.json @@ -82,6 +82,7 @@ "Clipperz/PM/DataModel/EncryptedRemoteObject.js", "Clipperz/PM/DataModel/User.js", + "Clipperz/PM/DataModel/User.AccountInfo.js", "Clipperz/PM/DataModel/User.Header.Legacy.js", "Clipperz/PM/DataModel/User.Header.RecordIndex.js", "Clipperz/PM/DataModel/User.Header.Preferences.js", @@ -171,6 +172,7 @@ "Clipperz/PM/UI/Web/Components/UnlockPasswordComponent.js", "Clipperz/PM/UI/Web/Components/NewUserCreationComponent.js", "Clipperz/PM/UI/Web/Components/PasswordTooltip.js", + "Clipperz/PM/UI/Web/Components/PaymentComponent.js", "Clipperz/PM/UI/Web/Controllers/MainController.js", "Clipperz/PM/UI/Web/Controllers/LoginController.js", @@ -182,6 +184,7 @@ "Clipperz/PM/UI/Web/Controllers/CardDialogController.js", "Clipperz/PM/UI/Web/Controllers/DirectLoginWizardController.js", "Clipperz/PM/UI/Web/Controllers/NewUserWizardController.js", + "Clipperz/PM/UI/Web/Controllers/PaymentController.js", "main.js" ], diff --git a/frontend/gamma/tests/tests/Clipperz/Base.test.js b/frontend/gamma/tests/tests/Clipperz/Base.test.js index 7ae611d..566f414 100644 --- a/frontend/gamma/tests/tests/Clipperz/Base.test.js +++ b/frontend/gamma/tests/tests/Clipperz/Base.test.js @@ -336,6 +336,27 @@ var tests = { */ }, + //------------------------------------------------------------------------- + + 'Clipperz.Base.isBitcoin_test': function () { + var bitcoinTestCases; + + bitcoinTestCases = [ + {url:'bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=20.3&label=Luke-Jr', expectedResult:true}, + {url:'bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W', expectedResult:true}, + + {url:'http://www.clipperz.com', expectedResult:false}, + {url:'http://clipperz.com', expectedResult:false}, + {} + ]; + + MochiKit.Base.map(function (someValues) { + if (typeof(someValues['url']) != 'undefined') { + SimpleTest.is(Clipperz.Base.isBitcoin(someValues['url']), someValues['expectedResult'], "testing url '" + someValues['url'] + "' - expected result: " + someValues['expectedResult']); + } + }, bitcoinTestCases); + }, + //------------------------------------------------------------------------- 'Clipperz.Base.isEmail_test': function () { diff --git a/frontend/gamma/tests/tests/Clipperz/PM/DataModel/DirectLogin.html b/frontend/gamma/tests/tests/Clipperz/PM/DataModel/DirectLogin.html index 74d1a07..640a4d1 100644 --- a/frontend/gamma/tests/tests/Clipperz/PM/DataModel/DirectLogin.html +++ b/frontend/gamma/tests/tests/Clipperz/PM/DataModel/DirectLogin.html @@ -73,6 +73,7 @@ refer to http://www.clipperz.com. + + + diff --git a/frontend/gamma/tests/tests/Clipperz/PM/DataModel/User.html b/frontend/gamma/tests/tests/Clipperz/PM/DataModel/User.html index 3a0eda8..48d9ad2 100644 --- a/frontend/gamma/tests/tests/Clipperz/PM/DataModel/User.html +++ b/frontend/gamma/tests/tests/Clipperz/PM/DataModel/User.html @@ -76,6 +76,7 @@ refer to http://www.clipperz.com. +