1
0
mirror of http://git.whoc.org.uk/git/password-manager.git synced 2025-10-29 18:37:35 +01:00

Final fixed before official /delta release

This commit is contained in:
Giulio Cesare Solaroli
2015-07-04 18:43:59 +02:00
parent 2e65e86341
commit e6d071a7c1
18 changed files with 520 additions and 691 deletions

View File

@@ -593,6 +593,7 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.DirectLogin, Object, {
},
'bindFormFieldWithLabelToRecordFieldWithLabel': function (aFormFieldLabel, aRecordFieldLabel) {
//console.log("DirectLogin.bindFormFieldWithLabelToCardFieldWithLabel", aFormFieldLabel, aRecordFieldLabel);
return Clipperz.Async.callbacks("DirectLogin.bindFormFieldWithLabelToCardFieldWithLabel", [
Clipperz.Async.collectResults("DirectLogin.bindFormFieldWithLabelToCardFieldWithLabel - collect results", {
'binding': [
@@ -604,7 +605,9 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.DirectLogin, Object, {
]
}),
function (someValues) {
someValues['binding'].setField(someValues['field'])
if (typeof(someValues['binding']) != 'undefined') {
someValues['binding'].setField(someValues['field']);
}
}
], {trace:false});
},
@@ -615,7 +618,15 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.DirectLogin, Object, {
return Clipperz.Async.callbacks("DirectLogin.setBindings", [
function () {
return MochiKit.Base.map(function (aBindingInfo) {
return self.bindFormFieldWithLabelToRecordFieldWithLabel(aBindingInfo[0], originalFields[aBindingInfo[1]]['label']);
var result;
try {
result = self.bindFormFieldWithLabelToRecordFieldWithLabel(aBindingInfo[0], originalFields[aBindingInfo[1]]['label']);
} catch (exception) {
result = MochiKit.Async.succeed();
}
return result;
}, MochiKit.Base.zip(MochiKit.Base.keys(someBindings), MochiKit.Base.values(someBindings)));
},
Clipperz.Async.collectAll,

View File

@@ -226,7 +226,7 @@ Clipperz.PM.UI.Components.ExtraFeatures.DataImport.InputClass = React.createClas
render: function() {
return React.DOM.div({},[
React.DOM.div({'className':'description'}, [
React.DOM.p({}, "You can import either CSV data, or Clipperz data exported in JSON"),
React.DOM.p({}, "Import data from a CSV file (like those produced by most password managers) or copy data from another Clipperz account using a JSON/HTML export file created by Clipperz."),
]),
React.DOM.form({'key':'form', 'className':'importForm' }, [
React.DOM.input({
@@ -239,16 +239,26 @@ Clipperz.PM.UI.Components.ExtraFeatures.DataImport.InputClass = React.createClas
React.DOM.div({
'onDragOver': this.handleOnDragOver,
'onDrop': this.handleOnDrop,
'onClick': MochiKit.Base.bind(function() { this.refs['upload-input'].getDOMNode().click() }, this),
'className': 'dropArea'
}, "Drag your Clipperz export file here or click select it manually."),
React.DOM.p({}, "or"),
}, [
React.DOM.span({}, "Drag your CSV or Clipperz export file here"),
React.DOM.br({}),
React.DOM.span({}, "or"),
React.DOM.br({}),
React.DOM.a({
'className': 'button',
'onClick': MochiKit.Base.bind(function() { this.refs['upload-input'].getDOMNode().click() }, this),
}, "select it manually")
]),
React.DOM.div({'className': 'description'},
React.DOM.p({}, "Alternatively you may type or paste any properly formatted CSV or JSON data.")
),
React.DOM.div({'key':'fields'},[
React.DOM.textarea({
'key':'input-textarea',
'name':'input-textarea',
'ref':'input-textarea',
'placeholder':"Copy or type your data here",
'placeholder':"Type or copy your data here",
'value': this.state.inputString,
'onChange': this.handleTextareaChange,
'onDragOver': this.handleOnDragOver,

View File

@@ -147,7 +147,10 @@ Clipperz.PM.UI.Components.ExtraFeatures.OTPClass = React.createClass({
renderOtpRows: function() {
var result;
var defaultOtpLabel;
defaultOtpLabel = "…";
if (this.props.userInfo.otpList) {
result = MochiKit.Base.map(MochiKit.Base.bind(function (anOTP) {
var reference = anOTP.reference();
@@ -177,11 +180,15 @@ Clipperz.PM.UI.Components.ExtraFeatures.OTPClass = React.createClass({
labelComponent = React.DOM.input({
'autoFocus':true,
'value':this.state.otpLabel,
'placeholder': "custom label",
'onChange':MochiKit.Base.partial(this.updateOtpLabel, anOTP),
'onKeyDown':MochiKit.Base.partial(this.handleKeyPressed, anOTP),
});
} else {
labelComponent = React.DOM.span({'onClick':MochiKit.Base.partial(this.enableOtpLabelEditing, anOTP)}, (anOTP.label()) ? anOTP.label() : "---")
labelComponent = React.DOM.span({
'onClick':MochiKit.Base.partial(this.enableOtpLabelEditing, anOTP),
'className': Clipperz.PM.UI.Components.classNames({'customLabel':anOTP.label()})
}, (anOTP.label()) ? anOTP.label() : defaultOtpLabel)
}
return React.DOM.li({
@@ -208,9 +215,9 @@ Clipperz.PM.UI.Components.ExtraFeatures.OTPClass = React.createClass({
render: function () {
return React.DOM.div({'className':'extraFeature OTP'}, [
React.DOM.div({'className':'header'}, [
React.DOM.h1({}, "One Time Passwords"),
React.DOM.h1({}, "One-Time Passwords"),
React.DOM.div({'className':'description'}, [
React.DOM.p({}, "A one-time passphrase works like your regular passphrase, but can be used only once. This makes it expecially useful for using it in places where keyloggers may be installed."),
React.DOM.p({}, "A one-time password works like your regular passphrase, but can be used only once. This makes it expecially useful for using it in places where keyloggers may be installed."),
]),
React.DOM.a({'className':'button', 'onClick':this.handlePrint}, "Print")
]),

View File

@@ -139,6 +139,12 @@ Clipperz.PM.UI.Components.Pages.LoginPageClass = React.createClass({
}
},
showUrl: function (anUrl) {
return function () {
window.open(anUrl, 'clipperz_about');
}
},
render: function() {
//console.log("LOGIN PAGE", this.props);
// var registrationLink = React.DOM.footer({'key':'registrationLink', 'className':'registrationLink'}, [
@@ -148,10 +154,20 @@ Clipperz.PM.UI.Components.Pages.LoginPageClass = React.createClass({
var registrationLink = React.DOM.a({'key':'signup', 'className':'registrationLink', 'onClick':this.handleRegistrationLinkClick}, "Sign up");
return React.DOM.div({'key':'loginForm', 'className':'loginForm ' + this.props['style']}, [
React.DOM.header({'key':'header'}, 'clipperz'),
React.DOM.header({'key':'header'}, [
React.DOM.h3({}, 'clipperz'),
React.DOM.h5({}, 'keep it to yourself'),
]),
React.DOM.div({'key':'formWrapper', 'className':'form'}, [
this.props.mode == 'PIN' ? this.pinForm() : this.loginForm(),
]),
React.DOM.div({'key':'links', 'className':'links'}, [
React.DOM.ul({}, [
React.DOM.li({'key':'about', 'onClick':this.showUrl('/about/')}, "About"),
React.DOM.li({'key':'terms', 'onClick':this.showUrl('/terms_service/')}, "Terms of service"),
React.DOM.li({'key':'privacy', 'onClick':this.showUrl('/privacy_policy/')}, "Privacy"),
])
]),
React.DOM.footer({'key':'footer'}, [
this.props['isNewUserRegistrationAvailable'] ? registrationLink : null,
React.DOM.div({'key':'applicationVersion', 'className':'applicationVersion'}, [

View File

@@ -214,6 +214,12 @@ Clipperz.PM.UI.Components.Pages.RegistrationPageClass = React.createClass({
]);
},
showUrl: function (anUrl) {
return function () {
window.open(anUrl, 'clipperz_about');
}
},
render: function () {
return React.DOM.div({'className':'registrationForm'},[
React.DOM.header({'key':'header'}, 'clipperz'),
@@ -222,6 +228,13 @@ Clipperz.PM.UI.Components.Pages.RegistrationPageClass = React.createClass({
React.DOM.div({'key':'steps', 'className':'steps'}, MochiKit.Base.map(this.renderStep, this.props['steps']))
])
]),
React.DOM.div({'key':'links', 'className':'links'}, [
React.DOM.ul({}, [
React.DOM.li({'key':'about', 'onClick':this.showUrl('/about/')}, "About"),
React.DOM.li({'key':'terms', 'onClick':this.showUrl('/terms_service/')}, "Terms of service"),
React.DOM.li({'key':'privacy', 'onClick':this.showUrl('/privacy_policy/')}, "Privacy"),
])
]),
React.DOM.footer({'key':'footer'}, [
React.DOM.a({'key':'login', 'onClick':this.handleLoginLinkClick}, "Login")
])

View File

@@ -53,6 +53,7 @@ Clipperz.PM.UI.Components.Panels.ExtraFeaturesPanelClass = React.createClass({
'account': false,
'subscription': false,
'data': false,
'about': false,
},
'isFullyOpen': false,
'extraFeatureComponentName': null,
@@ -73,6 +74,16 @@ Clipperz.PM.UI.Components.Panels.ExtraFeaturesPanelClass = React.createClass({
return (this.props['features'].indexOf(aValue) > -1);
},
showUrl: function (anUrl) {
return function () {
window.open(anUrl, 'clipperz_about');
}
},
logout: function () {
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'logout');
},
//=========================================================================
toggleExtraFeatureComponent: function (aComponentName) {
@@ -141,7 +152,7 @@ Clipperz.PM.UI.Components.Panels.ExtraFeaturesPanelClass = React.createClass({
// ])
]),
React.DOM.li({'key':'account_2', 'onClick':this.toggleExtraFeatureComponent('OTP')}, [
React.DOM.h2({}, "One Time Passwords"),
React.DOM.h2({}, "One-Time Passwords"),
// React.DOM.div({}, [
// React.DOM.p({}, "Manage your OTPs.")
// ])
@@ -230,6 +241,41 @@ Clipperz.PM.UI.Components.Panels.ExtraFeaturesPanelClass = React.createClass({
])
*/
])
]),
React.DOM.li({'key':'about', 'className':this.state['index']['about'] ? 'open' : 'closed'}, [
React.DOM.h1({'key':'aboutH1', 'onClick':this.toggleIndexState('about')}, "About"),
React.DOM.div({'key':'address', 'className':'address'}, [
"Clipperz Srl",
"Piazza Nuova, 10",
"48012 Bagnacavallo",
"Italy"
]),
React.DOM.ul({'key':'data'}, [
React.DOM.li({'key':'about_1', 'className':'link', 'onClick':this.showUrl('/')}, [
React.DOM.h2({}, "Website"),
]),
React.DOM.li({'key':'about_2', 'className':'link', 'onClick':this.showUrl('/forum/')}, [
React.DOM.h2({}, "Forum"),
]),
// React.DOM.li({'key':'about_3', 'className':'link', 'onClick':this.showUrl('/blog')}, [
// React.DOM.h2({}, "Blog"),
// ]),
React.DOM.li({'key':'about_4', 'className':'link', 'onClick':this.showUrl('https://twitter.com/clipperz')}, [
React.DOM.h2({}, "Twitter"),
]),
React.DOM.li({'key':'about_5', 'className':'link', 'onClick':this.showUrl('/about/contacts/')}, [
React.DOM.h2({}, "Contacts"),
]),
React.DOM.li({'key':'about_6', 'className':'link', 'onClick':this.showUrl('/terms_service/')}, [
React.DOM.h2({}, "Terms of service"),
]),
React.DOM.li({'key':'about_7', 'className':'link', 'onClick':this.showUrl('/privacy_policy/')}, [
React.DOM.h2({}, "Privacy"),
]),
])
]),
React.DOM.li({'key':'logout', 'className':'link', 'onClick':this.logout}, [
React.DOM.h2({}, "Logout")
])
])
]),

View File

@@ -275,11 +275,12 @@ MochiKit.Base.update(Clipperz.PM.UI.ExportController.prototype, {
'saveResult': function (exportedJSON) {
var blob;
var sortedJSON;
var now = new XDate();
var dateString = now.toString('yyyyMMdd');
sortedJSON = MochiKit.Iter.sorted(exportedJSON, function(a,b) { return a.label.toUpperCase().localeCompare(b.label.toUpperCase()); } );
blob = new Blob([this.renderToHtml(sortedJSON)], {type: "text/html;charset=utf-8"});
saveAs(blob, "clipperz_data.html");
saveAs(blob, dateString + '-Clipperz_Export.html');
},
//=============================================================================

View File

@@ -185,9 +185,13 @@ MochiKit.Base.update(Clipperz.PM.UI.ImportContext.prototype, {
},
enhanceJsonDataWithCardReferences: function (someJsonData) {
var now = new XDate();
var dateString = now.toString('yyyyMMdd');
return MochiKit.Base.map(function (item) {
item['reference'] = Clipperz.PM.Crypto.randomKey();
item['label'] = "COPY - " + item['label'];
// item['label'] = "COPY - " + item['label'];
item['label'] = item['label'] + ' ' + Clipperz.PM.DataModel.Record.tagChar + "Import_" + dateString;
return item;
}, someJsonData);
},

View File

@@ -62,6 +62,7 @@ Clipperz.PM.UI.MainController = function() {
this.registerForNotificationCenterEvents([
'doLogin', 'registerNewUser', 'showRegistrationForm', 'goBack',
'logout',
'changePassphrase', 'deleteAccount',
'updateOTPListAndDetails', 'createNewOTP', 'deleteOTPs', 'changeOTPLabel',
// 'export',
@@ -353,6 +354,19 @@ console.log("THE BROWSER IS OFFLINE");
return deferredResult;
},
logout_handler: function () {
var deferredResult;
deferredResult = new Clipperz.Async.Deferred('MainController.logout', {trace:false});
deferredResult.addMethod(this.user(), 'logout');
deferredResult.addCallback(function () {
window.location.href = '/';
})
deferredResult.callback();
return deferredResult;
},
//-------------------------------------------------------------------------
registerNewUser_handler: function (credentials) {