browser extension connector: implemented get-databasehash

This commit is contained in:
antelle 2021-04-07 21:08:22 +02:00
parent 933df5fae4
commit dc4742bf5c
No known key found for this signature in database
GPG Key ID: 63C9777AAB7C563C
5 changed files with 88 additions and 42 deletions

View File

@ -19,6 +19,10 @@ class FileCollection extends Collection {
getByName(name) {
return this.find((file) => file.name.toLowerCase() === name.toLowerCase());
}
firstActiveKdbxFile() {
return this.find((file) => file.active && !file.backend);
}
}
export { FileCollection };

View File

@ -97,11 +97,17 @@ const ProtocolHandlers = {
'get-databasehash'(request) {
decryptRequest(request);
return encryptResponse(request, {
action: 'hash',
version: RuntimeInfo.version,
hash: 'TODO'
});
const firstFile = AppModel.instance.files.firstActiveKdbxFile();
if (firstFile?.defaultGroupHash) {
return encryptResponse(request, {
action: 'hash',
version: RuntimeInfo.version,
hash: firstFile.defaultGroupHash
});
} else {
return { action: 'get-databasehash', error: 'No open files', errorCode: '1' };
}
}
};

View File

@ -469,7 +469,7 @@ class AppModel {
}
}
createNewFile(name) {
createNewFile(name, callback) {
if (!name) {
for (let i = 0; ; i++) {
name = Locale.openNewFile + (i || '');
@ -479,9 +479,10 @@ class AppModel {
}
}
const newFile = new FileModel({ id: IdGenerator.uuid() });
newFile.create(name);
this.addFile(newFile);
return newFile;
newFile.create(name, () => {
this.addFile(newFile);
callback?.(newFile);
});
}
openFile(params, callback) {

View File

@ -31,6 +31,9 @@ class FileModel extends Model {
kdbxweb.Kdbx.load(fileData, credentials)
.then((db) => {
this.db = db;
})
.then(() => this.setDefaultGroupHash())
.then(() => {
this.readModel();
this.setOpenFile({ passwordLength: password ? password.textLength : 0 });
if (keyFileData) {
@ -43,7 +46,7 @@ class FileModel extends Model {
': ' +
logger.ts(ts) +
', ' +
this.kdfArgsToString(db.header) +
this.kdfArgsToString(this.db.header) +
', ' +
Math.round(fileData.byteLength / 1024) +
' kB'
@ -90,13 +93,16 @@ class FileModel extends Model {
}
}
create(name) {
create(name, callback) {
const password = kdbxweb.ProtectedValue.fromString('');
const credentials = new kdbxweb.Credentials(password);
this.db = kdbxweb.Kdbx.create(credentials, name);
this.name = name;
this.readModel();
this.set({ active: true, created: true, name });
return this.setDefaultGroupHash().then(() => {
this.set({ active: true, created: true, name });
callback();
});
}
importWithXml(fileXml, callback) {
@ -107,6 +113,9 @@ class FileModel extends Model {
kdbxweb.Kdbx.loadXml(fileXml, credentials)
.then((db) => {
this.db = db;
})
.then(() => this.setDefaultGroupHash())
.then(() => {
this.readModel();
this.set({ active: true, created: true });
logger.info('Imported file ' + this.name + ': ' + logger.ts(ts));
@ -128,13 +137,17 @@ class FileModel extends Model {
const demoFile = kdbxweb.ByteUtils.arrayToBuffer(
kdbxweb.ByteUtils.base64ToBytes(demoFileData)
);
kdbxweb.Kdbx.load(demoFile, credentials).then((db) => {
this.db = db;
this.name = 'Demo';
this.readModel();
this.setOpenFile({ passwordLength: 4, demo: true });
callback();
});
kdbxweb.Kdbx.load(demoFile, credentials)
.then((db) => {
this.db = db;
})
.then(() => this.setDefaultGroupHash())
.then(() => {
this.name = 'Demo';
this.readModel();
this.setOpenFile({ passwordLength: 4, demo: true });
callback();
});
}
setOpenFile(props) {
@ -230,6 +243,17 @@ class FileModel extends Model {
}
}
setDefaultGroupHash() {
const uuidStr = kdbxweb.ByteUtils.bytesToHex(this.db.getDefaultGroup().uuid.bytes);
const uuidBytes = kdbxweb.ByteUtils.stringToBytes(uuidStr);
return kdbxweb.CryptoEngine.sha256(uuidBytes)
.then((hashBytes) => kdbxweb.ByteUtils.bytesToHex(hashBytes))
.then((defaultGroupHash) => {
this.set({ defaultGroupHash }, { silent: true });
});
}
subId(id) {
return this.id + ':' + id;
}
@ -770,7 +794,8 @@ FileModel.defineModelProperties({
supportsTags: true,
supportsColors: true,
supportsIcons: true,
supportsExpiration: true
supportsExpiration: true,
defaultGroupHash: ''
});
export { FileModel };

View File

@ -145,31 +145,41 @@ class ImportCsvView extends View {
runImport() {
let group = this.targetGroup;
let file = group ? group.file : undefined;
if (!group) {
let filePromise;
if (group) {
filePromise = Promise.resolve(group.file);
} else {
const fileName = this.fileName.replace(/\.csv$/i, '');
file = this.appModel.createNewFile(fileName);
group = file.groups[0];
filePromise = new Promise((resolve) => this.appModel.createNewFile(fileName, resolve));
}
for (const row of this.model.rows) {
const newEntry = EntryModel.newEntry(group, file);
for (let ix = 0; ix < row.length; ix++) {
let value = row[ix];
if (!value) {
continue;
}
const mapping = this.fieldMapping[ix];
if (mapping.type === 'ignore' || !mapping.field) {
continue;
}
if (mapping.field === 'Password') {
value = kdbxweb.ProtectedValue.fromString(value);
}
newEntry.setField(mapping.field, value);
filePromise.then((file) => {
if (!group) {
group = file.groups[0];
}
}
file.reload();
this.emit('done');
for (const row of this.model.rows) {
const newEntry = EntryModel.newEntry(group, file);
for (let ix = 0; ix < row.length; ix++) {
let value = row[ix];
if (!value) {
continue;
}
const mapping = this.fieldMapping[ix];
if (mapping.type === 'ignore' || !mapping.field) {
continue;
}
if (mapping.field === 'Password') {
value = kdbxweb.ProtectedValue.fromString(value);
}
newEntry.setField(mapping.field, value);
}
}
file.reload();
this.emit('done');
});
}
}