def test_merge(sources): runner = CliRunner(env={"KEEPASS_PASSWORD": '******'}) result_file = 'merged.kdbx' files = sources + [result_file] file_paths = [os.path.join('tests', fname) for fname in files] try: result = runner.invoke(main, file_paths) print(result.stdout) assert not result.exception, exc_to_str(result.exc_info) assert result.exit_code == 0, " ".join(file_paths) assert os.path.exists(file_paths[-1]) dest = PyKeePass(file_paths[-1], 'password') entries = dest.entries assert len(entries) == 3 michael = dest.find_entries_by_username('Michael321', first=True) assert michael.password == 'replaced' user = dest.find_entries_by_username('User Name', first=True) assert user.password == 'Password' orig = dest.find_entries_by_title('OnlyOriginal', first=True) assert orig is not None finally: if os.path.exists(file_paths[-1]): os.remove(file_paths[-1])
def test_processor(self): processor = Processor(vault_settings=self.vault_config, kdb_settings=self.kdb_config) processor.sync_from_kdb() processor.sync_from_vault() processor.write_vault() file_like = io.BytesIO() processor._kdb_settings["filename"] = file_like processor.write_kdb() file_like.seek(0) kdb = PyKeePass(filename=file_like, password=self.kdb_password) entry = kdb.find_entries_by_title(title="test_entry", first=True) self.assertEqual(entry.path, ["test", "sub", "test_entry"])
class EntryFunctionTests(unittest.TestCase): # get some things ready before testing def setUp(self): self.kp = PyKeePass(os.path.join(base_dir, 'test.kdbx'), password='******', keyfile=os.path.join(base_dir, 'test.key')) #---------- Finding entries ----------- def test_find_entries_by_title(self): results = self.kp.find_entries_by_title('root_entry') self.assertEqual(len(results), 1) results = self.kp.find_entries_by_title('Root_entry', regex=True, flags='i', first=True) self.assertEqual('root_entry', results.title) def test_find_entries_by_username(self): results = self.kp.find_entries_by_username('foobar_user') self.assertEqual(len(results), 2) results = self.kp.find_entries_by_username('Foobar_user', regex=True, flags='i', first=True) self.assertEqual('foobar_user', results.username) def test_find_entries_by_password(self): results = self.kp.find_entries_by_password('passw0rd') self.assertEqual(len(results), 2) results = self.kp.find_entries_by_password('Passw0rd', regex=True, flags='i', first=True) self.assertEqual('passw0rd', results.password) def test_find_entries_by_url(self): results = self.kp.find_entries_by_url('http://example.com') self.assertEqual(len(results), 2) results = self.kp.find_entries_by_url('http://example.com', first=True) self.assertEqual('http://example.com', results.url) def test_find_entries_by_notes(self): results = self.kp.find_entries_by_notes('entry notes') self.assertEqual(len(results), 1) results = self.kp.find_entries_by_notes('entry notes', regex=True) self.assertEqual(len(results), 2) results = self.kp.find_entries_by_notes('Entry notes', regex=True, flags='i', first=True) self.assertEqual('root entry notes', results.notes) def test_find_entries_by_path(self): results = self.kp.find_entries_by_path('foobar_group/group_entry') self.assertEqual(len(results), 1) results = self.kp.find_entries_by_path('foobar_group/Group_entry', regex=True, flags='i', first=True) self.assertIsInstance(results, Entry) self.assertEqual('group_entry', results.title) def test_find_entries_by_uuid(self): results = self.kp.find_entries_by_uuid('zF9+zSoASMqWIcIio0ewuw==')[0] self.assertIsInstance(results, Entry) self.assertEqual('zF9+zSoASMqWIcIio0ewuw==', results.uuid) self.assertEqual('foobar_user', results.username) def test_find_entries_by_string(self): results = self.kp.find_entries_by_string( {'custom_field': 'custom field value'})[0] self.assertIsInstance(results, Entry) self.assertEqual('custom field value', results.get_custom_property('custom_field')) self.assertEqual('HnN4bHSVjEybPf8nOq1bVA==', results.uuid) def test_find_entries(self): results = self.kp.find_entries(title='Root_entry', regex=True) self.assertEqual(len(results), 0) results = self.kp.find_entries(title='Root_entry', regex=True, flags='i', first=True) self.assertEqual('root_entry', results.title) results = self.kp.find_entries(url="http://example.com") self.assertEqual(len(results), 2) results = self.kp.find_entries(notes="entry notes", url="http://example.com") self.assertEqual(len(results), 1) self.assertTrue( self.kp.find_entries(title='group_entry', first=True) in results) # test `group` argument results = self.kp.find_entries(title='foobar_entry', group=None) self.assertEqual(len(results), 3) group = self.kp.find_groups(name='foobar_group', first=True) results = self.kp.find_entries(title='foobar_entry', group=group) self.assertEqual(len(results), 2) #---------- Adding/Deleting entries ----------- def test_add_delete_move_entry(self): unique_str = 'test_add_entry_' expiry_time = datetime.now() entry = self.kp.add_entry(self.kp.root_group, unique_str + 'title', unique_str + 'user', unique_str + 'pass', url=unique_str + 'url', notes=unique_str + 'notes', tags=unique_str + 'tags', expiry_time=expiry_time, icon=icons.KEY) results = self.kp.find_entries_by_title(unique_str + 'title') self.assertEqual(len(results), 1) results = self.kp.find_entries_by_title(unique_str + 'title', first=True) self.assertEqual(results.title, unique_str + 'title') self.assertEqual(results.username, unique_str + 'user') self.assertEqual(results.password, unique_str + 'pass') self.assertEqual(results.url, unique_str + 'url') self.assertEqual(results.notes, unique_str + 'notes') self.assertEqual(results.tags, [unique_str + 'tags']) # convert naive datetime to utc expiry_time_utc = expiry_time.replace(tzinfo=tz.gettz()).astimezone( tz.gettz('UTC')) self.assertEqual(results.icon, icons.KEY) sub_group = self.kp.add_group(self.kp.root_group, 'sub_group') self.kp.move_entry(entry, sub_group) results = self.kp.find_entries(path='sub_group/' + 'test_add_entry_title', first=True) self.assertEqual(results.title, entry.title) self.kp.delete_entry(entry) results = self.kp.find_entries_by_title(unique_str + 'title', first=True) self.assertIsNone(results) # test adding entry which exists in another group subgroup = self.kp.find_groups(name='subgroup2', first=True) self.kp.add_entry(subgroup, title='foobar_entry', username='******', password='******') # test adding entry to root which exists in subgroup self.kp.add_entry(subgroup, title='foobar_entry2', username='******', password='******') self.kp.add_entry(self.kp.root_group, title='foobar_entry2', username='******', password='******') #---------- Entries name collision exception ----------- def test_raise_exception_entry(self): unique_str = 'test_add_entry_' entry = self.kp.add_entry(self.kp.root_group, unique_str + 'title', unique_str + 'user', unique_str + 'pass', url=unique_str + 'url', notes=unique_str + 'notes', tags=unique_str + 'tags', icon=icons.KEY) self.assertRaises(Exception, entry) # ---------- Entries representation ----------- def test_print_entries(self): self.assertIsInstance(self.kp.entries.__repr__(), str)
class KeeFinder(object): def __init__(self, db_path, db_pass, verbosity): self.db = PyKeePass(db_path, db_pass) self.verbosity = verbosity self.found_entries = list() def find(self, strings): if not isinstance(strings, list): raise TypeError("Passed value has to be list type") self.found_entries = self._find_entries(strings[-1]) if not self.found_entries: return if len(strings) > 1: self.found_entries = self._find_in_entries(self.found_entries, strings[:-1]) def print_found(self): if not self.found_entries: print('Nothing found') return for entr in self.found_entries: self._print_entry(entr, self.verbosity) def _find_entries(self, substring, glob=True): search_string = substring.lower() res = list() if glob: search_string = '.*%s.*' % search_string method_names = ['title', 'username', 'url', 'password', 'path'] for method_name in method_names: method = getattr(self.db, 'find_entries_by_%s' % method_name) results = method(search_string, regex=True, flags='i') for result in results: if result not in res: res.append(result) root_group = self.db.find_groups_by_path('/') res_groups = list() # Now any group in res_groups will have a substring in path self._find_groups(substring, root_group, res_groups) for grp in res_groups: # As group has substring in path, it means any entry in this group # will have this substring in path too. There is no other way to do # this, sorry group_entries = self.db.find_entries_by_title('.*', regex=True, group=grp) for entr in group_entries: if entr not in res: res.append(entr) return res def _find_in_entries(self, entries, entry_names): survivors = entries.copy() while entry_names: entry_name = entry_names.pop() for index, entr in enumerate(entries): if not self._find_in_entry(entry_name, entr): survivors.remove(entr) survivors = self._find_in_entries(survivors, entry_names) return survivors def _find_in_entry(self, substring, entr): substring = substring.lower() if isinstance(entr, entry.Entry): subentries = [ entr.group.path, entr.title, entr.username, entr.password, entr.url ] elif isinstance(entr, group.Group): subentries = [entr.path] for subentry in subentries: if subentry and (substring in subentry.lower()): return True return False def _find_groups(self, name, root_groups, result=[]): for grp in root_groups: if name.lower() in grp.path.lower(): result.append(grp) subgroups = grp.subgroups self._find_groups(name, subgroups, result) def _print_entry(self, entr, verbosity): info = dict() def _get_fields(count): _info = dict() fields = ('group', 'username', 'password', 'title', 'url') if count == 2: fields = fields[:3] for field in fields: if field == 'group': _info[field] = entr.group.path else: _info[field] = getattr(entr, field) return _info if not verbosity: print(entr.password) elif verbosity == 1: print("%s - %s" % (entr.group.path, entr.username), file=sys.stderr) print(entr.password, end="") sys.stdout.flush() print("", file=sys.stderr) else: info = _get_fields(verbosity) if info: pprint.pprint(info) print()