mirror of https://github.com/keeweb/keeweb.git
protected fields support
This commit is contained in:
parent
db1909b313
commit
0c71955726
3
TODO.md
3
TODO.md
|
@ -10,7 +10,7 @@
|
|||
- [ ] switch view
|
||||
- [ ] optional auto-update
|
||||
- [ ] lock without closing
|
||||
- [ ] secure fields
|
||||
- [x] protected fields
|
||||
- [x] close files
|
||||
- [ ] show sync date
|
||||
- [x] offline and local storage
|
||||
|
@ -20,6 +20,7 @@
|
|||
- [ ] sync merge
|
||||
|
||||
## Future
|
||||
- [ ] secure inputs for all passwords
|
||||
- [ ] keepasshttp
|
||||
- [ ] mobile apps
|
||||
- [ ] file type associations
|
||||
|
|
|
@ -98,7 +98,7 @@ var DetailsView = Backbone.View.extend({
|
|||
var model = this.model;
|
||||
this.fieldViews.push(new FieldViewText({ model: { name: '$UserName', title: 'User',
|
||||
value: function() { return model.user; } } }));
|
||||
this.fieldViews.push(new FieldViewText({ model: { name: '$Password', title: 'Password',
|
||||
this.fieldViews.push(new FieldViewText({ model: { name: '$Password', title: 'Password', canGen: true,
|
||||
value: function() { return model.password; } } }));
|
||||
this.fieldViews.push(new FieldViewUrl({ model: { name: '$URL', title: 'Website',
|
||||
value: function() { return model.url; } } }));
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
'use strict';
|
||||
|
||||
var FieldViewText = require('./field-view-text'),
|
||||
Keys = require('../../const/keys');
|
||||
FieldView = require('./field-view'),
|
||||
Keys = require('../../const/keys'),
|
||||
kdbxweb = require('kdbxweb');
|
||||
|
||||
var FieldViewCustom = FieldViewText.extend({
|
||||
events: {
|
||||
'mousedown .details__field-label': 'fieldLabelMousedown',
|
||||
'mousedown .details__field-label': 'fieldLabelMousedown'
|
||||
},
|
||||
|
||||
initialize: function() {
|
||||
|
@ -19,6 +21,13 @@ var FieldViewCustom = FieldViewText.extend({
|
|||
this.$el.find('.details__field-label').text(this.model.newField);
|
||||
}
|
||||
this.$el.addClass('details__field--can-edit-title');
|
||||
if (this.isProtected === undefined) {
|
||||
this.isProtected = this.value instanceof kdbxweb.ProtectedValue;
|
||||
}
|
||||
this.protectBtn = $('<div/>').addClass('details__field-value-btn details__field-value-btn-protect')
|
||||
.toggleClass('details__field-value-btn-protect--protected', this.isProtected)
|
||||
.appendTo(this.valueEl)
|
||||
.mousedown(this.protectBtnClick.bind(this));
|
||||
},
|
||||
|
||||
endEdit: function(newVal, extra) {
|
||||
|
@ -32,7 +41,17 @@ var FieldViewCustom = FieldViewText.extend({
|
|||
this.$el.removeClass('details__field--can-edit-title');
|
||||
}
|
||||
extra = _.extend({}, extra, { newField: this.model.newField });
|
||||
FieldViewText.prototype.endEdit.call(this, newVal, extra);
|
||||
if (!this.editing) {
|
||||
return;
|
||||
}
|
||||
delete this.input;
|
||||
if (typeof newVal === 'string') {
|
||||
newVal = $.trim(newVal);
|
||||
if (this.isProtected) {
|
||||
newVal = kdbxweb.ProtectedValue.fromString(newVal);
|
||||
}
|
||||
}
|
||||
FieldView.prototype.endEdit.call(this, newVal, extra);
|
||||
},
|
||||
|
||||
startEditTitle: function() {
|
||||
|
@ -92,6 +111,11 @@ var FieldViewCustom = FieldViewText.extend({
|
|||
},
|
||||
|
||||
fieldValueBlur: function(e) {
|
||||
if (this.protectJustChanged) {
|
||||
this.protectJustChanged = false;
|
||||
e.target.focus();
|
||||
return;
|
||||
}
|
||||
this.endEdit(e.target.value);
|
||||
},
|
||||
|
||||
|
@ -120,6 +144,13 @@ var FieldViewCustom = FieldViewText.extend({
|
|||
$(e.target).unbind('blur');
|
||||
this.endEditTitle(e.target.value);
|
||||
}
|
||||
},
|
||||
|
||||
protectBtnClick: function(e) {
|
||||
e.stopPropagation();
|
||||
this.isProtected = !this.isProtected;
|
||||
this.protectBtn.toggleClass('details__field-value-btn-protect--protected', this.isProtected);
|
||||
this.protectJustChanged = true;
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -32,8 +32,8 @@ var FieldViewText = FieldView.extend({
|
|||
if (this.model.multiline) {
|
||||
this.setInputHeight();
|
||||
}
|
||||
if (this.value && this.value.byteLength) {
|
||||
$('<div/>').addClass('details__field-value-gen-btn').appendTo(this.valueEl)
|
||||
if (this.model.canGen) {
|
||||
$('<div/>').addClass('details__field-value-btn details__field-value-btn-gen').appendTo(this.valueEl)
|
||||
.click(this.showGeneratorClick.bind(this))
|
||||
.mousedown(this.showGenerator.bind(this));
|
||||
}
|
||||
|
|
|
@ -91,8 +91,10 @@ var FieldView = Backbone.View.extend({
|
|||
this.editing = false;
|
||||
var oldValText = this.value && this.value.getText ? this.value.getText() : this.value;
|
||||
var newValText = newVal && newVal.getText ? newVal.getText() : newVal;
|
||||
var textEqual = _.isEqual(newValText, oldValText);
|
||||
var protectedEqual = (newVal && typeof newVal.getText) === (this.value && typeof this.value.getText);
|
||||
var arg;
|
||||
if (newVal !== undefined && !_.isEqual(newValText, oldValText)) {
|
||||
if (newVal !== undefined && (!textEqual || !protectedEqual)) {
|
||||
arg = { val: newVal, field: this.model.name };
|
||||
if (extra) {
|
||||
_.extend(arg, extra);
|
||||
|
|
|
@ -224,7 +224,7 @@
|
|||
width: 12em;
|
||||
@include flex(0 0 auto);
|
||||
}
|
||||
&-gen-btn {
|
||||
&-btn {
|
||||
@include position(absolute, 0 0 null null);
|
||||
@include th { color: muted-color(); }
|
||||
cursor: pointer;
|
||||
|
@ -236,9 +236,13 @@
|
|||
@include fa-icon();
|
||||
cursor: pointer;
|
||||
padding: $base-padding;
|
||||
content: $fa-var-bolt;
|
||||
}
|
||||
}
|
||||
&-btn-gen:before { content: $fa-var-bolt; }
|
||||
&-btn-protect {
|
||||
&:before { content: $fa-var-unlock; }
|
||||
&--protected:before { content: $fa-var-lock; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ Release notes
|
|||
##### v0.2.0 (not released yet)
|
||||
UX improvements, new features, bugfixes
|
||||
`+` improved open page ux
|
||||
`+` protected fields support
|
||||
`+` keyfiles from Dropbox
|
||||
`+` #17: option to hide entries from subgroups
|
||||
`+` #5: groups and entries arranging
|
||||
|
|
Loading…
Reference in New Issue