diff --git a/api/ovdashboard_api/config.py b/api/ovdashboard_api/config.py index c072eaf..f50d807 100644 --- a/api/ovdashboard_api/config.py +++ b/api/ovdashboard_api/config.py @@ -48,7 +48,7 @@ class Config(BaseModel): Load the configuration instance from the server using `TOML`. """ - dav_file = DavFile("config.txt") + dav_file = DavFile("ovdashboard/config.txt") try: return cls.parse_obj( diff --git a/api/ovdashboard_api/dav_common.py b/api/ovdashboard_api/dav_common.py index 5654b0b..81faab5 100644 --- a/api/ovdashboard_api/dav_common.py +++ b/api/ovdashboard_api/dav_common.py @@ -14,9 +14,9 @@ from .async_helpers import run_in_executor from .settings import SETTINGS _WEBDAV_CLIENT = WebDAVclient({ - "webdav_hostname": SETTINGS.webdav_url, - "webdav_login": SETTINGS.dav_username, - "webdav_password": SETTINGS.dav_password, + "webdav_hostname": SETTINGS.webdav.url, + "webdav_login": SETTINGS.webdav.username, + "webdav_password": SETTINGS.webdav.password, }) @@ -39,9 +39,9 @@ def webdav_list(remote_path: str) -> list[str]: _CALDAV_CLIENT = CalDAVclient( - url=SETTINGS.caldav_url, - username=SETTINGS.dav_username, - password=SETTINGS.dav_password, + url=SETTINGS.caldav.url, + username=SETTINGS.caldav.username, + password=SETTINGS.caldav.password, ) diff --git a/api/ovdashboard_api/routers/image.py b/api/ovdashboard_api/routers/image.py index a2652c0..bbb403a 100644 --- a/api/ovdashboard_api/routers/image.py +++ b/api/ovdashboard_api/routers/image.py @@ -62,7 +62,7 @@ async def get_image( prefix: str, name: str = Depends(_unique), ) -> str: - dav_file = DavFile(f"{_lister.remote_path}/{name}") + dav_file = DavFile(f"ovdashboard/{_lister.remote_path}/{name}") img = Image.open(BytesIO(await dav_file.bytes)).convert("RGB") img_buffer = BytesIO() diff --git a/api/ovdashboard_api/routers/text.py b/api/ovdashboard_api/routers/text.py index a32f5c3..acad336 100644 --- a/api/ovdashboard_api/routers/text.py +++ b/api/ovdashboard_api/routers/text.py @@ -22,7 +22,7 @@ from ._common import FileNameLister, PrefixFinder, PrefixUnique router = APIRouter(prefix="/text", tags=["text"]) _lister = FileNameLister( - remote_path="text", + remote_path="ovdashboard/text", re=re.compile( r"\.(txt|md)$", flags=re.IGNORECASE, @@ -34,7 +34,7 @@ _unique = PrefixUnique(_finder) async def get_ticker_lines() -> Iterator[str]: - ticker = await DavFile("text/ticker.txt").string + ticker = await DavFile("ovdashboard/text/ticker.txt").string return ( line.strip() @@ -104,7 +104,7 @@ async def find_texts( async def get_text_content( name: str = Depends(_unique), ) -> str: - return await DavFile(f"{_lister.remote_path}/{name}").string + return await DavFile(f"ovdashboard/{_lister.remote_path}/{name}").string @router.get( diff --git a/api/ovdashboard_api/settings.py b/api/ovdashboard_api/settings.py index aeae1e5..2e26052 100644 --- a/api/ovdashboard_api/settings.py +++ b/api/ovdashboard_api/settings.py @@ -9,12 +9,42 @@ Pydantic models might have convenience methods attached. from typing import Optional -from pydantic import BaseSettings +from pydantic import BaseModel, BaseSettings, root_validator + + +class DavSettings(BaseModel): + """ + Connection to a DAV server. + """ + + protocol: Optional[str] + host: Optional[str] + username: Optional[str] + password: Optional[str] + path: Optional[str] + + @property + def url(self) -> str: + """ + Combined DAV URL. + """ + + return f"{self.protocol}://{self.host}{self.path}" + + @classmethod + @property + def default(cls) -> "DavSettings": + return cls( + protocol="https", + host="example.com", + username="ovdashboard", + password="secret", + ) class Settings(BaseSettings): """ - Per-run settings + Per-run settings. """ production_mode: bool = False @@ -23,33 +53,41 @@ class Settings(BaseSettings): docs_url: Optional[str] = "/docs" redoc_url: Optional[str] = "/redoc" - caldav_base_url: str = "/remote.php/dav" - webdav_base_url: str = "/remote.php/webdav/ovdashboard" - dav_protocol: str = "https" - dav_host: str = "example.com" - dav_username: str = "ovdashboard" - dav_password: str = "changeme" - dav_path: str = "ovdashboard" + webdav: DavSettings = DavSettings() + caldav: DavSettings = DavSettings() cache_seconds: int = 30 - @property - def caldav_url(self) -> str: - """ - Combined CalDAV URL. - """ + class Config: + env_nested_delimiter = "__" - return f"{self.dav_protocol}://" + \ - f"{self.dav_host}{self.caldav_base_url}" + @root_validator(pre=True) + @classmethod + def validate_dav_settings(cls, values): + # ensure both settings dicts are created + for key in ("webdav", "caldav"): + if key not in values: + values[key] = {} - @property - def webdav_url(self) -> str: - """ - Combined WebDAV URL. - """ + default_dav = DavSettings.default.dict() - return f"{self.dav_protocol}://" + \ - f"{self.dav_host}{self.webdav_base_url}" + for key in default_dav: + # if "webdav" value is not specified, use default + if key not in values["webdav"]: + values["webdav"][key] = default_dav[key] + + # if "caldav" value is not specified, use "webdav" value + if key not in values["caldav"]: + values["caldav"][key] = values["webdav"][key] + + # add default "path"s if None + if values["webdav"]["path"] is None: + values["webdav"]["path"] = "/remote.php/webdav" + + if values["caldav"]["path"] is None: + values["caldav"]["path"] = "/remote.php/dav" + + return values SETTINGS = Settings(_env_file=".env")