Compare commits

..

No commits in common. "main" and "0.1.0a32" have entirely different histories.

5 changed files with 217 additions and 64 deletions

View file

@ -1,44 +1,193 @@
## 1.0.0 (2026-06-21) ## 0.1.0a32 (2026-06-11)
### Fix
- doc
## 0.1.0a31 (2026-05-04)
### Feat ### Feat
- multi layers - multi layers
- improvment + Calculation with hidden
- use Calculation ## 0.1.0a30 (2026-01-21)
- doc
- update rougail-structural-bitwarden
- use user_datas to load datas
- update rougail-structural-bitwarden package version
- port to rougail secret_manager
- same behavour between bw et rbw
- support rbw and bw command line
- first version
### Fix ### Fix
- rougail dependencies
- black
- remove old structural dependency
- doc
- transfert part a secretmanager in rougail - transfert part a secretmanager in rougail
## 0.1.0a29 (2025-12-30)
### Fix
- update tests - update tests
## 0.1.0a28 (2025-12-23)
### Feat
- improvment + Calculation with hidden
## 0.1.0a27 (2025-12-22)
### Feat
- use Calculation
- doc
## 0.1.0a26 (2025-11-21)
### Fix
- ExtentionError => ExtensionError - ExtentionError => ExtensionError
## 0.1.0a25 (2025-11-06)
### Fix
- disable config if bitwarden is not selected - disable config if bitwarden is not selected
## 0.1.0a24 (2025-10-16)
### Fix
- path is uncalculated - path is uncalculated
## 0.1.0a23 (2025-10-16)
### Feat
- update rougail-structural-bitwarden
## 0.1.0a22 (2025-10-10)
### Feat
- use user_datas to load datas
## 0.1.0a21 (2025-06-20)
### Feat
- update rougail-structural-bitwarden package version
## 0.1.0a20 (2025-05-12)
### Fix
- black - black
## 0.1.0a19 (2025-05-02)
### Fix
- do not force use_data usage - do not force use_data usage
## 0.1.0a18 (2025-04-09)
### Fix
- version - version
## 0.1.0a17 (2025-04-09)
### Fix
- better error message - better error message
## 0.1.0a16 (2025-04-04)
### Fix
- with ROUGAIL_BITWARDEN_MOCK_ENABLE variable, unix_user and password are different - with ROUGAIL_BITWARDEN_MOCK_ENABLE variable, unix_user and password are different
## 0.1.0a15 (2025-03-19)
### Fix
- support item without username - support item without username
## 0.1.0a14 (2025-03-19)
### Feat
- port to rougail secret_manager
- same behavour between bw et rbw
## 0.1.0a13 (2025-02-19)
### Fix
- MOCK - MOCK
## 0.1.0a12 (2025-02-19)
### Fix
- MOCK - MOCK
## 0.1.0a11 (2025-02-19)
### Fix
- if mock is active, do not search rbw or bw - if mock is active, do not search rbw or bw
## 0.1.0a10 (2025-02-17)
### Fix
- support hidden attribut - support hidden attribut
## 0.1.0a9 (2025-02-17)
### Fix
- support hidden attribut - support hidden attribut
## 0.1.0a8 (2025-02-17)
### Fix
- update structural plugin version - update structural plugin version
## 0.1.0a7 (2025-02-17)
### Feat
- support rbw and bw command line
## 0.1.0a6 (2025-02-13)
### Fix
- bitwarden key could be an invalid username/secret - bitwarden key could be an invalid username/secret
## 0.1.0a5 (2025-02-13)
### Fix
- structural load - structural load
## 0.1.0a4 (2025-02-13)
### Fix
- structural version - structural version
## 0.1.0a2 (2025-02-13)
### Fix
- separate user-data and structural - separate user-data and structural
## 0.1.0a1 (2025-02-12)
### Fix
- many improvment - many improvment
## 0.1.0a0 (2025-02-05)
### Feat
- first version

View file

@ -4,7 +4,7 @@ requires = ["flit_core >=3.8.0,<4"]
[project] [project]
name = "rougail.user_data_bitwarden" name = "rougail.user_data_bitwarden"
version = "1.0.0" version = "0.1.0a32"
authors = [{name = "Emmanuel Garette", email = "gnunux@gnunux.info"}] authors = [{name = "Emmanuel Garette", email = "gnunux@gnunux.info"}]
readme = "README.md" readme = "README.md"
description = "Rougail user_data Bitwarden" description = "Rougail user_data Bitwarden"
@ -24,7 +24,8 @@ classifiers = [
] ]
dependencies = [ dependencies = [
"rougail >= 1.2.0,<2", "rougail >= 1.1,<2",
"rougail-structural-bitwarden == 0.1.0a6",
] ]
[project.urls] [project.urls]

View file

@ -1 +1 @@
__version__ = "1.0.0" __version__ = "0.1.0a32"

View file

@ -18,7 +18,6 @@ You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
""" """
from rougail.error import DictConsistencyError from rougail.error import DictConsistencyError
from rougail.annotator.variable import Walk from rougail.annotator.variable import Walk

View file

@ -32,16 +32,11 @@ from .i18n import _
class FakeBW: class FakeBW:
def get_key( def get_key(
self, self,
key_bitwarden: str, key_bitwarden: str,
leader: bool, leader: bool,
): ):
return [ return [{'name': key_bitwarden, 'login': {'username': "example_login", 'password': "Ex4mpL3_P4ssw0rD"}}]
{
"name": key_bitwarden,
"login": {"username": "example_login", "password": "Ex4mpL3_P4ssw0rD"},
}
]
class RBW: class RBW:
@ -53,10 +48,10 @@ class RBW:
return cpe.returncode == 0 return cpe.returncode == 0
def get_key( def get_key(
self, self,
key_bitwarden: str, key_bitwarden: str,
leader: bool, leader: bool,
): ):
keys = [] keys = []
items = run_commandline(["rbw", "search", key_bitwarden]).strip() items = run_commandline(["rbw", "search", key_bitwarden]).strip()
if items: if items:
@ -77,7 +72,9 @@ class RBW:
datas = [] datas = []
for key in sorted(keys): for key in sorted(keys):
data = loads( data = loads(
run_commandline(["rbw", "get", key, "--raw", "--ignorecase"]).strip() run_commandline(
["rbw", "get", key, "--raw", "--ignorecase"]
).strip()
) )
datas.append({"name": key, "login": data["data"]}) datas.append({"name": key, "login": data["data"]})
return datas return datas
@ -100,10 +97,10 @@ class BW:
return False return False
def get_key( def get_key(
self, self,
key_bitwarden: str, key_bitwarden: str,
*args, *args,
): ):
return loads( return loads(
run_commandline( run_commandline(
["bw", "list", "items", "--search", key_bitwarden, "--nointeraction"] ["bw", "list", "items", "--search", key_bitwarden, "--nointeraction"]
@ -146,10 +143,9 @@ class RougailUserDataBitwarden:
self.errors = [] self.errors = []
self.warnings = [] self.warnings = []
self.cache = {} self.cache = {}
self.commands = { self.commands = {'rbw': RBW(),
"rbw": RBW(), 'bw': BW(),
"bw": BW(), }
}
def run(self): def run(self):
values = {} values = {}
@ -157,13 +153,13 @@ class RougailUserDataBitwarden:
self.set_passwords(self.config.unrestraint, values) self.set_passwords(self.config.unrestraint, values)
return [ return [
{ {
"source": "Bitwarden", "source": 'Bitwarden',
"errors": self.errors, "errors": self.errors,
"warnings": self.warnings, "warnings": self.warnings,
"values": values, "values": values,
"options": { "options": {
"secret_manager": True, "secret_manager": True,
}, }
} }
] ]
@ -190,11 +186,7 @@ class RougailUserDataBitwarden:
if option.isoptiondescription(): if option.isoptiondescription():
self.set_passwords(option, values) self.set_passwords(option, values)
elif option.information.get("bitwarden", False): elif option.information.get("bitwarden", False):
values[option.path(uncalculated=True)] = ( values[option.path(uncalculated=True)] = (set_password, self.cache, self.command)
set_password,
self.cache,
self.command,
)
def set_password(cache, command, *, option): def set_password(cache, command, *, option):
@ -203,7 +195,9 @@ def set_password(cache, command, *, option):
if leader: if leader:
key = key[0] key = key[0]
if not isinstance(key, str): if not isinstance(key, str):
raise ConfigError(_("the default value must be the Bitwarden item name")) raise ConfigError(
_('the default value must be the Bitwarden item name')
)
if key in cache: if key in cache:
data = cache[key] data = cache[key]
if option.isfollower(): if option.isfollower():
@ -214,21 +208,27 @@ def set_password(cache, command, *, option):
data = command.get_key(key, leader) data = command.get_key(key, leader)
except Exception as exc: except Exception as exc:
raise ConfigError( raise ConfigError(
_('cannot execute the "{0}" commandline from Bitwarden: {1}').format( _(
command, exc 'cannot execute the "{0}" commandline from Bitwarden: {1}'
) ).format(command, exc)
) )
cache[key] = data.copy() cache[key] = data.copy()
if not data: if not data:
raise ConfigError(_('item "{0}" in Bitwarden is not found').format(key)) raise ConfigError(
_('item "{0}" in Bitwarden is not found').format(
key
)
)
type_ = option.information.get("type") type_ = option.information.get("type")
if leader: if leader:
return [get_value(key, type_, d) for d in data] return [
get_value(key, type_, d) for d in data
]
if len(data) != 1: if len(data) != 1:
raise ConfigError( raise ConfigError(
_('several items found with name "{0}" in Bitwarden: "{1}"').format( _(
key, '", "'.join([d["name"] for d in data]) 'several items found with name "{0}" in Bitwarden: "{1}"'
) ).format(key, '", "'.join([d["name"] for d in data]))
) )
return get_value(key, type_, data[0]) return get_value(key, type_, data[0])
@ -241,7 +241,9 @@ def get_value(key_bitwarden: str, type_: str, data: dict) -> str:
value = data["login"]["username"] value = data["login"]["username"]
except Exception as exc: except Exception as exc:
raise ConfigError( raise ConfigError(
_('unexpected datas "{0}" from Bitwarden: {1}').format(key_bitwarden, exc) _('unexpected datas "{0}" from Bitwarden: {1}').format(
key_bitwarden, exc
)
) )
if value is None: if value is None:
if type_ == "secret": if type_ == "secret":
@ -249,6 +251,8 @@ def get_value(key_bitwarden: str, type_: str, data: dict) -> str:
else: else:
bw_type = _("username") bw_type = _("username")
raise ConfigError( raise ConfigError(
_('item "{0}" in Bitwarden has no {1}').format(key_bitwarden, bw_type) _('item "{0}" in Bitwarden has no {1}').format(
key_bitwarden, bw_type
)
) )
return value return value