Nested collections support
I have added support for nesting collections when importing a keepass file with multiple nested folders as mentioned in #42
If the -nestcoll switch is enabled, if required, it creates subcollections under the given parent collection from -bwcoll, also I have turned off folder creation for this option, as it does not seem pertinent to create folders when you are already creating subcollections
I am open to any suggestions as I am not a native python programmer, also the code could use some optimization as far as api calls are concerened
I tried running this via your branch but can't get it to work. My Keypass file has 3 levels deep. In Bitwarden I have it pointing to an empty collection at root level.
I also tried with a basic file with just 1 level of folders inside.
kp2bw -bworg 1234567890 -bwcoll 1234567890 "E:\tmp\Bitwarden Import\KeypassFile.kdbx" -nestcoll
Returns the following.
Traceback (most recent call last):
File "<frozen runpy>", line 198, in _run_module_as_main
File "<frozen runpy>", line 88, in _run_code
File "E:\tmp\Bitwarden Import\kp2bw-master-nested-collections\.env\kp2bw\Scripts\kp2bw.exe\__main__.py", line 7, in <module>
File "E:\tmp\Bitwarden Import\kp2bw-master-nested-collections\.env\kp2bw\Lib\site-packages\kp2bw\cli.py", line 88, in main
c.convert()
File "E:\tmp\Bitwarden Import\kp2bw-master-nested-collections\.env\kp2bw\Lib\site-packages\kp2bw\convert.py", line 338, in convert
self._create_bitwarden_items_for_entries()
File "E:\tmp\Bitwarden Import\kp2bw-master-nested-collections\.env\kp2bw\Lib\site-packages\kp2bw\convert.py", line 265, in _create_bitwarden_items_for_entries
childId = bw._create_sub_colllection(bw._parent_name + "/" + folder, self._bitwarden_coll_id)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "E:\tmp\Bitwarden Import\kp2bw-master-nested-collections\.env\kp2bw\Lib\site-packages\kp2bw\bitwardenclient.py", line 117, in _create_sub_colllection
childCreate = json.loads(self._exec_with_session(f"bw get template org-collection --session '{self._key}' | jq \".name = \\\"{collname}\\\" |.groups = [] | .organizationId=\\\"{self._orgId}\\\"\" | bw encode | bw create org-collection --organizationid {self._orgId}"))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Python312\Lib\json\__init__.py", line 346, in loads
return _default_decoder.decode(s)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Python312\Lib\json\decoder.py", line 337, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Python312\Lib\json\decoder.py", line 355, in raw_decode
raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
Ah ha. It was due to the lack of having jq on my system. Edited your code change to exclude jq and just use the built in JSON library instead.
newCol = json.loads(self._exec_with_session(f"bw get template org-collection --session '{self._key}'"))
newCol["name"] = collname
newCol["group"] = []
newCol["organizationId"] = self._orgId
data_b64 = base64.b64encode(json.dumps(newCol).encode("UTF-8")).decode("UTF-8")
childCreate = json.loads(self._exec_with_session(f"{self._get_platform_dependent_echo_str(data_b64)} | bw create org-collection --organizationid {self._orgId}"))
Not the prettiest but it does work as a proof of concept.