Merge pull request 'pass_context' (#10) from pass_context into develop
Reviewed-on: https://hattori.ztsh.eu/paas/karl/pulls/10
This commit is contained in:
commit
8cf4f719b5
10 changed files with 24 additions and 26 deletions
|
|
@ -10,6 +10,7 @@ class Request:
|
|||
started: str
|
||||
files: List[str]
|
||||
|
||||
|
||||
@dataclass
|
||||
class Response:
|
||||
status: int
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
from dataclasses import dataclass, field
|
||||
from typing import Type
|
||||
|
||||
|
||||
# TODO: unnecessary?
|
||||
|
||||
@dataclass
|
||||
|
|
@ -8,6 +9,7 @@ class PathItem:
|
|||
name: str
|
||||
t: Type
|
||||
|
||||
|
||||
@dataclass
|
||||
class Path:
|
||||
path: list[PathItem] = field(default_factory=list)
|
||||
|
|
@ -43,6 +45,7 @@ class Password:
|
|||
def path(self):
|
||||
return self.group.path.append(self.name, type(self))
|
||||
|
||||
|
||||
class UnencryptedPassword(Password):
|
||||
def __init__(self, name: str, value: str, group: Group):
|
||||
super().__init__(name, group)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
from dataclasses import dataclass
|
||||
from typing import List
|
||||
|
||||
|
||||
@dataclass
|
||||
class WoodpeckerEvent:
|
||||
_id: str
|
||||
|
|
|
|||
|
|
@ -38,4 +38,3 @@ class DockerService:
|
|||
def reload(self, compose_path: Path):
|
||||
cmd = ["sudo", "docker", "compose", "-f", str(compose_path), "up", "-d"]
|
||||
# TODO: subprocess
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ class SimpleValueTemplate(Template):
|
|||
|
||||
|
||||
class ComplexValueTemplate(SimpleValueTemplate):
|
||||
delimiter = '@'
|
||||
delimiter = '%'
|
||||
|
||||
|
||||
@injectable
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import os.path
|
||||
import shutil
|
||||
from contextlib import contextmanager
|
||||
from typing import Any, Generator
|
||||
|
||||
import keyring
|
||||
from injectable import injectable
|
||||
from pykeepass import PyKeePass, create_database
|
||||
|
||||
|
|
@ -12,22 +14,16 @@ class Passwords:
|
|||
settings = get_settings()
|
||||
|
||||
with open(settings.kp.secret, "r") as fh:
|
||||
secret = fh.read().splitlines()[0]
|
||||
keyring.set_password("karl", "kp", fh.read().splitlines()[0])
|
||||
self._path = settings.kp.file
|
||||
self._kp_org = self._open_or_create(self._path, secret)
|
||||
self._kp = self._open_lock(self._path, secret)
|
||||
|
||||
@staticmethod
|
||||
def _open_or_create(path, password) -> PyKeePass:
|
||||
if os.path.exists(path):
|
||||
return PyKeePass(path, password=password)
|
||||
return create_database(path, password)
|
||||
|
||||
@staticmethod
|
||||
def _open_lock(path, password) -> PyKeePass:
|
||||
lock_path = path + ".lock"
|
||||
shutil.copyfile(path, lock_path)
|
||||
return Passwords._open_or_create(lock_path, password)
|
||||
@contextmanager
|
||||
def open(self, mode: str = "r") -> Generator[PyKeePass | Any, Any, None]:
|
||||
kp = PyKeePass(self._path, password=keyring.get_password("karl", "kp")) \
|
||||
if os.path.exists(self._path) else create_database(self._path, password=keyring.get_password("karl", "kp"))
|
||||
yield kp
|
||||
if mode == "rw":
|
||||
kp.save()
|
||||
|
||||
def get_values(self, keys: list[str]) -> dict[str, str]:
|
||||
output = {}
|
||||
|
|
@ -36,7 +32,8 @@ class Passwords:
|
|||
path = key_parts[:-1] if len(key_parts) > 2 else None
|
||||
entry_name = key_parts[-2]
|
||||
field_name = key_parts[-1]
|
||||
kp_entry = self._kp_org.find_entries(path=path, first=True, title=entry_name)
|
||||
with self.open() as kp:
|
||||
kp_entry = kp.find_entries(path=path, first=True, title=entry_name)
|
||||
output[k] = self._get_field_value(kp_entry, field_name)
|
||||
return output
|
||||
|
||||
|
|
@ -53,8 +50,3 @@ class Passwords:
|
|||
return kp_entry.url
|
||||
case _:
|
||||
return kp_entry.get_custom_property(field_name)
|
||||
|
||||
def save(self):
|
||||
# nadpisz plik źródłowy zmianami z lock
|
||||
self._kp.save()
|
||||
shutil.copyfile(self._path + ".lock", self._path)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>{{ title }}</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||
<meta content="width=device-width, initial-scale=1" name="viewport"/>
|
||||
<style>
|
||||
body {
|
||||
font-family: system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, Helvetica, Arial, "Apple Color Emoji", "Segoe UI Emoji";
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ dependencies = [
|
|||
"injectable==4.0.1",
|
||||
"py-automapper>=2.2.0",
|
||||
"fastapi-utils>=0.8.0",
|
||||
"keyring>=25.6.0",
|
||||
]
|
||||
|
||||
[project.optional-dependencies]
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
value: ${sample}
|
||||
nested: ${some.nested.value}
|
||||
custom: @{custom.field}
|
||||
custom: %{custom.field}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ class TestMo(TestCase):
|
|||
with open(target_path, 'r') as f:
|
||||
content = f.read()
|
||||
self.assertFalse(content.__contains__('${'))
|
||||
self.assertFalse(content.__contains__('%{'))
|
||||
parsed = yaml.load(content, Loader=yaml.FullLoader)
|
||||
self.assertEqual('some_pass', parsed['value'])
|
||||
self.assertEqual('nested_pass', parsed['nested'])
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue