mirror of https://github.com/keeweb/keeweb.git
otp bugfixes
This commit is contained in:
parent
8b3e1e4f3c
commit
8252d72598
|
@ -6,7 +6,8 @@ var Timeouts = {
|
|||
AutoHideHint: 3000,
|
||||
FileChangeSync: 3000,
|
||||
BeforeAutoLock: 300,
|
||||
CheckWindowClosed: 300
|
||||
CheckWindowClosed: 300,
|
||||
OtpFadeDuration: 10000
|
||||
};
|
||||
|
||||
module.exports = Timeouts;
|
||||
|
|
|
@ -371,7 +371,6 @@ var EntryModel = Backbone.Model.extend({
|
|||
},
|
||||
|
||||
initOtpGenerator: function() {
|
||||
this.otpGenerator = null;
|
||||
var otpUrl;
|
||||
if (this.fields.otp) {
|
||||
otpUrl = this.fields.otp;
|
||||
|
@ -391,8 +390,7 @@ var EntryModel = Backbone.Model.extend({
|
|||
(args.size ? '&digits=' + args.size : '');
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.fields['TOTP Seed']) {
|
||||
} else if (this.fields['TOTP Seed']) {
|
||||
// TrayTOTP plugin format
|
||||
var key = this.fields['TOTP Seed'];
|
||||
if (key.isProtected) {
|
||||
|
@ -417,17 +415,26 @@ var EntryModel = Backbone.Model.extend({
|
|||
this.fields.otp = kdbxweb.ProtectedValue.fromString(otpUrl);
|
||||
}
|
||||
if (otpUrl) {
|
||||
if (this.otpGenerator && this.otpGenerator.url === otpUrl) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
this.otpGenerator = Otp.parseUrl(otpUrl);
|
||||
} catch (e) {
|
||||
this.otpGenerator = null;
|
||||
}
|
||||
} else {
|
||||
this.otpGenerator = null;
|
||||
}
|
||||
},
|
||||
|
||||
setOtp: function(otp) {
|
||||
this.otpGenerator = otp;
|
||||
this.setField('otp', kdbxweb.ProtectedValue.fromString(otp.url));
|
||||
this.setOtpUrl(otp.url);
|
||||
},
|
||||
|
||||
setOtpUrl: function(url) {
|
||||
this.setField('otp', kdbxweb.ProtectedValue.fromString(url));
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -158,7 +158,7 @@ var DetailsView = Backbone.View.extend({
|
|||
this.fieldViews.push(new FieldViewHistory({ model: { name: 'History', title: Locale.detHistory,
|
||||
value: function() { return { length: model.historyLength, unsaved: model.unsaved }; } } }));
|
||||
_.forEach(model.fields, function(value, field) {
|
||||
if (field.toLowerCase() === 'otp' && this.model.otpGenerator) {
|
||||
if (field === 'otp' && this.model.otpGenerator) {
|
||||
this.fieldViews.push(new FieldViewOtp({ model: { name: '$' + field, title: field,
|
||||
value: function() { return model.otpGenerator; } } }));
|
||||
} else {
|
||||
|
@ -434,7 +434,12 @@ var DetailsView = Backbone.View.extend({
|
|||
if (e.field) {
|
||||
if (e.field[0] === '$') {
|
||||
var fieldName = e.field.substr(1);
|
||||
if (e.newField) {
|
||||
if (fieldName === 'otp') {
|
||||
if (this.otpFieldChanged(e.val)) {
|
||||
this.entryUpdated();
|
||||
return;
|
||||
}
|
||||
} else if (e.newField) {
|
||||
if (fieldName) {
|
||||
this.model.setField(fieldName, undefined);
|
||||
}
|
||||
|
@ -478,6 +483,18 @@ var DetailsView = Backbone.View.extend({
|
|||
}
|
||||
},
|
||||
|
||||
otpFieldChanged: function(value) {
|
||||
var oldValue = this.model.fields.otp;
|
||||
if (oldValue && oldValue.isProtected) {
|
||||
oldValue = oldValue.getText();
|
||||
}
|
||||
if (oldValue === value) {
|
||||
return false;
|
||||
}
|
||||
this.model.setOtpUrl(value);
|
||||
return true;
|
||||
},
|
||||
|
||||
fieldCopied: function(e) {
|
||||
if (this.fieldCopyTip) {
|
||||
this.fieldCopyTip.hide();
|
||||
|
|
|
@ -1,15 +1,22 @@
|
|||
'use strict';
|
||||
|
||||
var FieldViewText = require('./field-view-text');
|
||||
var FieldViewText = require('./field-view-text'),
|
||||
Timeouts = require('../../const/timeouts');
|
||||
|
||||
var MinOpacity = 0.2;
|
||||
|
||||
var FieldViewOtp = FieldViewText.extend({
|
||||
otpTimeout: null,
|
||||
otpTickInterval: null,
|
||||
otpValue: null,
|
||||
otpGenerator: null,
|
||||
otpTimeLeft: 0,
|
||||
otpValidUntil: 0,
|
||||
fieldOpacity: null,
|
||||
|
||||
renderValue: function(value) {
|
||||
this.resetOtpTimer();
|
||||
if (!value) {
|
||||
this.resetOtp();
|
||||
return '';
|
||||
}
|
||||
if (value !== this.otpGenerator) {
|
||||
|
@ -23,16 +30,29 @@ var FieldViewOtp = FieldViewText.extend({
|
|||
return value && value.url;
|
||||
},
|
||||
|
||||
render: function() {
|
||||
FieldViewText.prototype.render.call(this);
|
||||
this.fieldOpacity = null;
|
||||
this.otpTick();
|
||||
},
|
||||
|
||||
remove: function() {
|
||||
this.resetOtpTimer();
|
||||
this.value = null;
|
||||
this.otpGenerator = null;
|
||||
this.resetOtp();
|
||||
FieldViewText.prototype.remove.apply(this, arguments);
|
||||
},
|
||||
|
||||
resetOtpTimer: function() {
|
||||
resetOtp: function() {
|
||||
this.otpGenerator = null;
|
||||
this.otpValue = null;
|
||||
this.otpTimeLeft = 0;
|
||||
this.otpValidUntil = 0;
|
||||
if (this.otpTimeout) {
|
||||
clearTimeout(this.otpTimeout);
|
||||
this.otpTimeout = null;
|
||||
}
|
||||
if (this.otpTickInterval) {
|
||||
clearInterval(this.otpTickInterval);
|
||||
this.otpTickInterval = null;
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -43,14 +63,40 @@ var FieldViewOtp = FieldViewText.extend({
|
|||
},
|
||||
|
||||
otpUpdated: function(pass, timeLeft) {
|
||||
if (!this.value) {
|
||||
if (!this.value || !pass) {
|
||||
this.resetOtp();
|
||||
return;
|
||||
}
|
||||
this.otpValue = pass || '';
|
||||
this.otpTimeLeft = timeLeft || 0;
|
||||
this.otpValidUntil = Date.now() + timeLeft;
|
||||
this.render();
|
||||
if (this.otpValue && timeLeft) {
|
||||
this.otpTimeout = setTimeout(this.requestOtpUpdate.bind(this), timeLeft);
|
||||
if (!this.otpTickInterval) {
|
||||
this.otpTickInterval = setInterval(this.otpTick.bind(this), 300);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
otpTick: function() {
|
||||
if (!this.value || !this.otpValidUntil) {
|
||||
return;
|
||||
}
|
||||
var opacity;
|
||||
var timeLeft = this.otpValidUntil - Date.now();
|
||||
if (timeLeft >= Timeouts.OtpFadeDuration || this.editing) {
|
||||
opacity = 1;
|
||||
} else if (timeLeft <= 0) {
|
||||
opacity = MinOpacity;
|
||||
} else {
|
||||
opacity = Math.max(MinOpacity, Math.pow(timeLeft / Timeouts.OtpFadeDuration, 2));
|
||||
}
|
||||
if (this.fieldOpacity === opacity) {
|
||||
return;
|
||||
}
|
||||
this.fieldOpacity = opacity;
|
||||
this.valueEl.css('opacity', opacity);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in New Issue