From 9ab5766680aa0e24105638d24124dda3476bff4b Mon Sep 17 00:00:00 2001 From: muddykat-tech Date: Wed, 17 Apr 2024 05:29:49 +1000 Subject: [PATCH] Basic Foundation for a Keeper Security JSON Importer --- .project | 11 +++ source/importers/KeeperSecurityImporter.js | 101 +++++++++++++++++++++ source/index.js | 2 + 3 files changed, 114 insertions(+) create mode 100644 .project create mode 100644 source/importers/KeeperSecurityImporter.js diff --git a/.project b/.project new file mode 100644 index 0000000..dd25054 --- /dev/null +++ b/.project @@ -0,0 +1,11 @@ + + + buttercup-importer + + + + + + + + diff --git a/source/importers/KeeperSecurityImporter.js b/source/importers/KeeperSecurityImporter.js new file mode 100644 index 0000000..4cdb353 --- /dev/null +++ b/source/importers/KeeperSecurityImporter.js @@ -0,0 +1,101 @@ +const fs = require("fs/promises"); +const { + Vault, + Entry, + createEntryFacade, + consumeEntryFacade, +} = require("buttercup"); + +const DEFAULT_GROUP = "General"; + +/** + * Importer for Keeper Security vaults + * @memberof module:ButtercupImporter + */ +class KeeperSecurityImporter { + /** + * Create a new Keeper Security importer + * @param {String} data Raw JSON data of a Keeper Security vault export + */ + constructor(data) { + this._data = data; + } + + /** + * Export to a Buttercup vault + * @returns {Promise.} + * @memberof KeeperSecurityImporter + */ + export() { + const groups = {}; + return Promise.resolve().then(() => { + const vault = new Vault(); + const ksJson = JSON.parse(this._data); // Parse the new JSON data + + // Create the root group + const rootGroup = vault.createGroup(DEFAULT_GROUP); + groups[null] = rootGroup; + + ksJson.records.forEach((record) => { + if (record.folders) { + var folderPath = record.folders[0].folder; + var folders = folderPath + .split("\\") + .map((folderName) => folderName.trim()); + + var currentGroup = rootGroup; + + for ( + var folderIndex = 0; + folderIndex < folders.length; + folderIndex += 1 + ) { + if (groups[folders[folderIndex]] != undefined) { + currentGroup = groups[folders[folderIndex]]; + } else { + currentGroup = currentGroup.createGroup( + folders[folderIndex] + ); + + // Section untested due to an odd issue with createEntry not instancing correctly? + const entry = currentGroup.createEntry( + record.title + ); + entry.setProperty( + "username", + record.login == null ? "" : record.login + ); + entry.setProperty( + "password", + record.password == null ? "" : record.password + ); + entry.setProperty( + "URL", + record.login_url == null ? "" : record.login_url + ); + + groups[folders[folderIndex]] = currentGroup; + } + } + } + }); + + return vault; + }); + } +} + +/** + * Load an importer from a file + * @param {String} filename The file to load from + * @returns {Promise.} + * @static + * @memberof KeeperSecurityImporter + */ +KeeperSecurityImporter.loadFromFile = function (filename) { + return fs + .readFile(filename, "utf8") + .then((data) => new KeeperSecurityImporter(data)); +}; + +module.exports = KeeperSecurityImporter; diff --git a/source/index.js b/source/index.js index a26e2f2..17ffd7b 100644 --- a/source/index.js +++ b/source/index.js @@ -5,6 +5,7 @@ const CSVImporter = require("./importers/CSVImporter.js"); const KeePass2XMLImporter = require("./importers/KeePass2XMLImporter.js"); const LastPassImporter = require("./importers/LastPassImporter.js"); const OnePasswordImporter = require("./importers/OnePasswordImporter.js"); +const KeeperSecurityImporter = require("./importers/KeeperSecurityImporter.js"); /** * @module ButtercupImporter @@ -18,4 +19,5 @@ module.exports = { KeePass2XMLImporter, LastPassImporter, OnePasswordImporter, + KeeperSecurityImporter, };