Compare commits

...

6 commits

5 changed files with 79 additions and 232 deletions

View file

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

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 = "0.1.0a32" version = "1.0.0"
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,8 +24,7 @@ classifiers = [
] ]
dependencies = [ dependencies = [
"rougail >= 1.1,<2", "rougail >= 1.2.0,<2",
"rougail-structural-bitwarden == 0.1.0a6",
] ]
[project.urls] [project.urls]

View file

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

View file

@ -8,25 +8,26 @@ This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation; either version 2 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License 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
class Annotator(Walk): class Annotator(Walk):
"""Annotate for bitwarden""" """Annotate for bitwarden"""
level = 90 level = 90
def __init__( def __init__(
self, self,
objectspace, objectspace,

View file

@ -32,11 +32,16 @@ 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 [{'name': key_bitwarden, 'login': {'username': "example_login", 'password': "Ex4mpL3_P4ssw0rD"}}] return [
{
"name": key_bitwarden,
"login": {"username": "example_login", "password": "Ex4mpL3_P4ssw0rD"},
}
]
class RBW: class RBW:
@ -48,10 +53,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:
@ -72,9 +77,7 @@ class RBW:
datas = [] datas = []
for key in sorted(keys): for key in sorted(keys):
data = loads( data = loads(
run_commandline( run_commandline(["rbw", "get", key, "--raw", "--ignorecase"]).strip()
["rbw", "get", key, "--raw", "--ignorecase"]
).strip()
) )
datas.append({"name": key, "login": data["data"]}) datas.append({"name": key, "login": data["data"]})
return datas return datas
@ -97,10 +100,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"]
@ -143,9 +146,10 @@ class RougailUserDataBitwarden:
self.errors = [] self.errors = []
self.warnings = [] self.warnings = []
self.cache = {} self.cache = {}
self.commands = {'rbw': RBW(), self.commands = {
'bw': BW(), "rbw": RBW(),
} "bw": BW(),
}
def run(self): def run(self):
values = {} values = {}
@ -153,13 +157,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,
} },
} }
] ]
@ -186,7 +190,11 @@ 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)] = (set_password, self.cache, self.command) values[option.path(uncalculated=True)] = (
set_password,
self.cache,
self.command,
)
def set_password(cache, command, *, option): def set_password(cache, command, *, option):
@ -195,9 +203,7 @@ 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( raise ConfigError(_("the default value must be the Bitwarden item name"))
_('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():
@ -208,27 +214,21 @@ 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(
'cannot execute the "{0}" commandline from Bitwarden: {1}' command, exc
).format(command, exc) )
) )
cache[key] = data.copy() cache[key] = data.copy()
if not data: if not data:
raise ConfigError( raise ConfigError(_('item "{0}" in Bitwarden is not found').format(key))
_('item "{0}" in Bitwarden is not found').format(
key
)
)
type_ = option.information.get("type") type_ = option.information.get("type")
if leader: if leader:
return [ return [get_value(key, type_, d) for d in data]
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(
'several items found with name "{0}" in Bitwarden: "{1}"' key, '", "'.join([d["name"] for d in data])
).format(key, '", "'.join([d["name"] for d in data])) )
) )
return get_value(key, type_, data[0]) return get_value(key, type_, data[0])
@ -241,9 +241,7 @@ 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( _('unexpected datas "{0}" from Bitwarden: {1}').format(key_bitwarden, exc)
key_bitwarden, exc
)
) )
if value is None: if value is None:
if type_ == "secret": if type_ == "secret":
@ -251,8 +249,6 @@ 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( _('item "{0}" in Bitwarden has no {1}').format(key_bitwarden, bw_type)
key_bitwarden, bw_type
)
) )
return value return value