Create views for organizing secrets in groups

This commit is contained in:
2025-06-01 15:06:07 +02:00
parent 773a1e2976
commit ba936ac645
28 changed files with 1152 additions and 396 deletions

View File

@ -23,7 +23,13 @@ from sshecret.crypto import encrypt_string, load_public_key
from .keepass import PasswordContext, load_password_manager
from sshecret_admin.core.settings import AdminServerSettings
from .models import ClientSecretGroup, SecretClientMapping, SecretGroup, SecretView
from .models import (
ClientSecretGroup,
ClientSecretGroupList,
SecretClientMapping,
SecretGroup,
SecretView,
)
class ClientManagementError(Exception):
@ -353,7 +359,7 @@ class AdminBackend:
self,
group_filter: str | None = None,
regex: bool = True,
) -> list[ClientSecretGroup]:
) -> ClientSecretGroupList:
"""Get secret groups.
The starting group can be filtered with the group_name argument, which
@ -363,19 +369,33 @@ class AdminBackend:
secrets_mapping = {secret.name: secret for secret in all_secrets}
with self.password_manager() as password_manager:
all_groups = password_manager.get_secret_groups(group_filter, regex=regex)
ungrouped = password_manager.get_ungrouped_secrets()
result: list[ClientSecretGroup] = []
group_result: list[ClientSecretGroup] = []
for group in all_groups:
# We have to do this recursively.
result.append(add_clients_to_secret_group(group, secrets_mapping))
group_result.append(add_clients_to_secret_group(group, secrets_mapping))
result = ClientSecretGroupList(groups=group_result)
if group_filter:
return result
ungrouped_clients: list[SecretClientMapping] = []
for name in ungrouped:
mapping = SecretClientMapping(name=name)
if client_mapping := secrets_mapping.get(name):
mapping.clients = client_mapping.clients
ungrouped_clients.append(mapping)
result.ungrouped = ungrouped_clients
return result
async def get_secret_group(self, name: str) -> ClientSecretGroup | None:
"""Get a single secret group by name."""
matches = await self.get_secret_groups(group_filter=name, regex=False)
if not matches:
return None
return matches[0]
if matches.groups:
return matches.groups[0]
return None
async def get_secret(self, name: str) -> SecretView | None:
"""Get secrets from backend."""
@ -390,10 +410,11 @@ class AdminBackend:
"""Get a secret, including the actual unencrypted value and clients."""
with self.password_manager() as password_manager:
secret = password_manager.get_secret(name)
secret_group = password_manager.get_entry_group(name)
if not secret:
return None
secret_view = SecretView(name=name, secret=secret)
secret_view = SecretView(name=name, secret=secret, group=secret_group)
secret_mapping = await self.backend.get_secret(name)
if secret_mapping:
secret_view.clients = secret_mapping.clients