#!/usr/bin/env python3 import argparse import json import sqlite3 from vinetrimmer.utils.AtomicSQL import AtomicSQL class LocalVault: def __init__(self, vault_path): """ Update local key vault to newer system. This should ONLY be run if you have the old structure with keys in a table named `keys`. It will move and update the structure of the items in `keys` to their respective new locations and structure. :param vault_path: sqlite db path """ self.adb = AtomicSQL() self.ticket = self.adb.load(sqlite3.connect(vault_path)) if not self.table_exists("keys"): return rows = self.adb.safe_execute( self.ticket, lambda db, cursor: cursor.execute("SELECT `service`, `title`, `content_keys` FROM `keys`") ).fetchall() for service, title, content_keys in rows: service = service.lower() content_keys = json.loads(content_keys) if not self.table_exists(service): self.create_table(service) for kid, key in [x.split(":") for x in content_keys]: print(f"Inserting: {kid} {key} {title}") existing_row, existing_title = self.row_exists(service, kid, key) if existing_row: if title and not existing_title: print(" -- exists, but the title doesn't, so ill merge") self.adb.safe_execute( self.ticket, lambda db, cursor: cursor.execute( f"UPDATE `{service}` SET `title`=? WHERE `kid`=? AND `key_`=?", (title, kid, key) ) ) continue print(" -- skipping (exists already)") continue self.adb.safe_execute( self.ticket, lambda db, cursor: cursor.execute( f"INSERT INTO `{service}` (kid, key_, title) VALUES (?, ?, ?)", (kid, key, title) ) ) self.adb.commit(self.ticket) def row_exists(self, table, kid, key): return self.adb.safe_execute( self.ticket, lambda db, cursor: cursor.execute( f"SELECT count(id), title FROM `{table}` WHERE kid=? AND key_=?", [kid, key] ) ).fetchone() def table_exists(self, name): return self.adb.safe_execute( self.ticket, lambda db, cursor: cursor.execute( "SELECT count(name) FROM sqlite_master WHERE type='table' AND name=?", [name.lower()] ) ).fetchone()[0] == 1 def create_table(self, name): self.adb.safe_execute( self.ticket, lambda db, cursor: cursor.execute( """ CREATE TABLE {} ( "id" INTEGER NOT NULL UNIQUE, "kid" TEXT NOT NULL COLLATE NOCASE, "key_" TEXT NOT NULL COLLATE NOCASE, "title" TEXT NULL, PRIMARY KEY("id" AUTOINCREMENT), UNIQUE("kid", "key_") ); """.format(name.lower()) ) ) parser = argparse.ArgumentParser() parser.add_argument( "-i", "--input", help="vault", required=True) args = parser.parse_args() LocalVault(args.input)