keeweb/app/scripts/models/entry-model.js

294 lines
8.7 KiB
JavaScript
Raw Normal View History

2015-10-17 23:49:24 +02:00
'use strict';
var Backbone = require('backbone'),
AttachmentModel = require('./attachment-model'),
IconMap = require('../const/icon-map'),
Color = require('../util/color'),
2015-11-21 21:14:21 +01:00
IconUrl = require('../util/icon-url'),
2015-10-17 23:49:24 +02:00
kdbxweb = require('kdbxweb');
var EntryModel = Backbone.Model.extend({
defaults: {},
buildInFields: ['Title', 'Password', 'Notes', 'URL', 'UserName'],
initialize: function() {
},
setEntry: function(entry, group, file) {
this.entry = entry;
this.group = group;
this.file = file;
2015-12-05 14:04:09 +01:00
if (this.id === entry.uuid.id) {
this._checkUpdatedEntry();
}
2015-10-17 23:49:24 +02:00
this._fillByEntry();
},
_fillByEntry: function() {
var entry = this.entry;
2015-12-05 14:04:09 +01:00
this.set({id: entry.uuid.id}, {silent: true});
2015-12-13 15:59:41 +01:00
this.fileName = this.file.get('name');
2015-10-17 23:49:24 +02:00
this.title = entry.fields.Title || '';
2015-10-31 20:27:31 +01:00
this.password = entry.fields.Password || kdbxweb.ProtectedValue.fromString('');
2015-10-17 23:49:24 +02:00
this.notes = entry.fields.Notes || '';
this.url = entry.fields.URL || '';
this.user = entry.fields.UserName || '';
this.iconId = entry.icon;
this.icon = this._iconFromId(entry.icon);
this.tags = entry.tags;
this.color = this._colorToModel(entry.bgColor) || this._colorToModel(entry.fgColor);
this.fields = this._fieldsToModel(entry.fields);
this.attachments = this._attachmentsToModel(entry.binaries);
this.created = entry.times.creationTime;
this.updated = entry.times.lastModTime;
this.expires = entry.times.expires ? entry.times.expiryTime : undefined;
this.expired = entry.times.expires && entry.times.expiryTime <= new Date();
this.historyLength = entry.history.length;
2015-11-12 22:52:28 +01:00
this._buildCustomIcon();
2015-10-17 23:49:24 +02:00
this._buildSearchText();
this._buildSearchTags();
this._buildSearchColor();
},
2015-12-05 14:04:09 +01:00
_checkUpdatedEntry: function() {
if (this.isJustCreated) {
this.isJustCreated = false;
}
if (this.unsaved && +this.updated !== +this.entry.times.lastModTime) {
this.unsaved = false;
}
},
2015-10-17 23:49:24 +02:00
_buildSearchText: function() {
var text = '';
_.forEach(this.entry.fields, function(value) {
if (typeof value === 'string') {
text += value.toLowerCase() + '\n';
}
});
this.entry.tags.forEach(function(tag) {
text += tag.toLowerCase() + '\n';
});
this.attachments.forEach(function(att) {
text += att.title.toLowerCase() + '\n';
});
this.searchText = text;
},
2015-11-12 22:52:28 +01:00
_buildCustomIcon: function() {
this.customIcon = null;
2015-11-21 23:15:51 +01:00
this.customIconId = null;
2015-11-12 22:52:28 +01:00
if (this.entry.customIcon) {
2015-11-21 21:14:21 +01:00
this.customIcon = IconUrl.toDataUrl(this.file.db.meta.customIcons[this.entry.customIcon]);
2015-11-21 23:15:51 +01:00
this.customIconId = this.entry.customIcon.toString();
2015-11-12 22:52:28 +01:00
}
},
2015-10-17 23:49:24 +02:00
_buildSearchTags: function() {
this.searchTags = this.entry.tags.map(function(tag) { return tag.toLowerCase(); });
},
_buildSearchColor: function() {
this.searchColor = this.color;
},
_iconFromId: function(id) {
return IconMap[id];
},
_colorToModel: function(color) {
return color ? Color.getNearest(color) : null;
},
_fieldsToModel: function(fields) {
return _.omit(fields, this.buildInFields);
},
_attachmentsToModel: function(binaries) {
var att = [];
_.forEach(binaries, function(data, title) {
2015-12-17 21:22:36 +01:00
if (data && data.ref) {
data = this.file.db.meta.binaries[data.ref];
}
if (data) {
att.push(AttachmentModel.fromAttachment({data: data, title: title}));
}
2015-10-17 23:49:24 +02:00
}, this);
return att;
},
_entryModified: function() {
if (!this.unsaved) {
this.unsaved = true;
this.entry.pushHistory();
this.file.setModified();
}
2015-10-27 22:07:48 +01:00
if (this.isJustCreated) {
this.isJustCreated = false;
2015-10-27 20:40:34 +01:00
}
2015-10-17 23:49:24 +02:00
this.entry.times.update();
},
matches: function(filter) {
2015-12-05 14:04:09 +01:00
return !filter ||
(!filter.tagLower || this.searchTags.indexOf(filter.tagLower) >= 0) &&
2015-10-17 23:49:24 +02:00
(!filter.textLower || this.searchText.indexOf(filter.textLower) >= 0) &&
(!filter.color || filter.color === true && this.searchColor || this.searchColor === filter.color);
},
setColor: function(color) {
this._entryModified();
this.entry.bgColor = Color.getKnownBgColor(color);
this._fillByEntry();
},
setIcon: function(iconId) {
this._entryModified();
this.entry.icon = iconId;
2015-11-21 23:15:51 +01:00
this.entry.customIcon = undefined;
this._fillByEntry();
},
setCustomIcon: function(customIconId) {
this._entryModified();
this.entry.customIcon = new kdbxweb.KdbxUuid(customIconId);
2015-10-17 23:49:24 +02:00
this._fillByEntry();
},
setExpires: function(dt) {
this._entryModified();
this.entry.times.expiryTime = dt instanceof Date ? dt : undefined;
this.entry.times.expires = !!dt;
this._fillByEntry();
},
setTags: function(tags) {
this._entryModified();
this.entry.tags = tags;
this._fillByEntry();
},
setField: function(field, val) {
this._entryModified();
2015-11-10 18:23:50 +01:00
var hasValue = val && (typeof val === 'string' || val instanceof kdbxweb.ProtectedValue && val.byteLength);
if (hasValue || this.buildInFields.indexOf(field) >= 0) {
2015-10-17 23:49:24 +02:00
this.entry.fields[field] = val;
} else {
delete this.entry.fields[field];
}
this._fillByEntry();
},
hasField: function(field) {
return this.entry.fields.hasOwnProperty(field);
},
addAttachment: function(name, data) {
this._entryModified();
2015-12-17 21:22:36 +01:00
var binaryId;
for (var i = 0; ; i++) {
if (!this.file.db.meta.binaries[i]) {
binaryId = i.toString();
break;
}
}
this.file.db.meta.binaries[binaryId] = data;
this.entry.binaries[name] = { ref: binaryId };
2015-10-17 23:49:24 +02:00
this._fillByEntry();
},
removeAttachment: function(name) {
this._entryModified();
delete this.entry.binaries[name];
this._fillByEntry();
},
getHistory: function() {
var history = this.entry.history.map(function(rec) {
return EntryModel.fromEntry(rec, this.group, this.file);
}, this);
history.push(this);
history.sort(function(x, y) { return x.updated - y.updated; });
return history;
},
deleteHistory: function(historyEntry) {
var ix = this.entry.history.indexOf(historyEntry);
if (ix >= 0) {
2015-12-05 14:04:09 +01:00
this.entry.removeHistory(ix);
2015-10-17 23:49:24 +02:00
}
this._fillByEntry();
},
revertToHistoryState: function(historyEntry) {
var ix = this.entry.history.indexOf(historyEntry);
if (ix < 0) {
return;
}
this.entry.pushHistory();
this.unsaved = true;
this.file.setModified();
this.entry.fields = {};
this.entry.binaries = {};
this.entry.copyFrom(historyEntry);
this._entryModified();
this._fillByEntry();
},
discardUnsaved: function() {
2015-12-05 14:04:09 +01:00
if (this.unsaved && this.entry.history.length) {
2015-10-17 23:49:24 +02:00
this.unsaved = false;
2015-12-05 14:04:09 +01:00
var historyEntry = this.entry.history[this.entry.history.length - 1];
this.entry.removeHistory(this.entry.history.length - 1);
2015-10-17 23:49:24 +02:00
this.entry.fields = {};
this.entry.binaries = {};
this.entry.copyFrom(historyEntry);
this._fillByEntry();
}
},
moveToTrash: function() {
2015-11-19 06:55:45 +01:00
this.file.setModified();
if (this.isJustCreated) {
this.isJustCreated = false;
}
2015-11-04 09:06:49 +01:00
this.file.db.remove(this.entry);
2015-12-05 14:04:09 +01:00
this.file.reload();
2015-10-27 20:40:34 +01:00
},
2015-11-09 19:15:39 +01:00
deleteFromTrash: function() {
2015-11-19 06:55:45 +01:00
this.file.setModified();
2015-11-09 19:15:39 +01:00
this.file.db.move(this.entry, null);
2015-12-05 14:04:09 +01:00
this.file.reload();
2015-11-09 19:15:39 +01:00
},
2015-10-27 20:40:34 +01:00
removeWithoutHistory: function() {
var ix = this.group.group.entries.indexOf(this.entry);
if (ix >= 0) {
this.group.group.entries.splice(ix, 1);
}
2015-12-05 14:04:09 +01:00
this.file.reload();
2015-10-17 23:49:24 +02:00
}
});
EntryModel.fromEntry = function(entry, group, file) {
var model = new EntryModel();
model.setEntry(entry, group, file);
return model;
};
EntryModel.newEntry = function(group, file) {
var model = new EntryModel();
var entry = file.db.createEntry(group.group);
model.setEntry(entry, group, file);
model.entry.times.update();
model.unsaved = true;
2015-10-27 22:07:48 +01:00
model.isJustCreated = true;
2015-10-27 20:40:34 +01:00
group.addEntry(model);
2015-10-17 23:49:24 +02:00
file.setModified();
return model;
};
module.exports = EntryModel;