config.py 4.74 KiB
from typing import Any
import secrets
import json
import toml
import os
from pydantic import BaseSettings, BaseModel, PostgresDsn, AnyHttpUrl, EmailStr, validator
# For more information how BaseSettings work, check the documentation:
# https://pydantic-docs.helpmanual.io/usage/settings/
# This is inspired by
# https://github.com/tiangolo/full-stack-fastapi-postgresql/blob/490c554e23343eec0736b06e59b2108fdd057fdc/%7B%7Bcookiecutter.project_slug%7D%7D/backend/app/app/core/config.py
class ServerConfig(BaseModel):
HOST: str = 'localhost' # host to run this server on
PORT: int = 8080 # port for this serve to listen at
DEBUG_MODE: bool = False # set this to true in order to get more detailed logs
WORKERS: int = 2 # number of worker processes
STATIC_FILES: str = '../nacsos-web/dist/' # path to the static files to be served
OPENAPI_FILE: str = '/openapi.json' # absolute URL path to openapi.json file
OPENAPI_PREFIX: str = '' # see https://fastapi.tiangolo.com/advanced/behind-a-proxy/
ROOT_PATH: str = '' # see https://fastapi.tiangolo.com/advanced/behind-a-proxy/
HASH_ALGORITHM: str = 'HS256'
SECRET_KEY: str = secrets.token_urlsafe(32)
ACCESS_TOKEN_EXPIRE_MINUTES: int = 60 * 24 * 8 # = 8 days
HEADER_CORS: bool = False # set to true to allow CORS
HEADER_TRUSTED_HOST: bool = False # set to true to allow hosts from any origin
CORS_ORIGINS: list[AnyHttpUrl] = [] # list of trusted hosts
@validator("CORS_ORIGINS", pre=True)
def assemble_cors_origins(cls, v: str | list[str]) -> str | list[str]:
if isinstance(v, str) and not v.startswith('['):
return [i.strip() for i in v.split(',')]
if isinstance(v, str) and v.startswith('['):
ret = json.loads(v)
if type(ret) == list:
return ret
elif isinstance(v, (list, str)):
return v
raise ValueError(v)
class DatabaseConfig(BaseModel):
HOST: str = 'localhost' # host of the db server
PORT: int = 5432 # port of the db server
USER: str = 'nacsos' # username for the database
PASSWORD: str = 'secr€t_passvvord' # password for the database user
DATABASE: str = 'nacsos_core' # name of the database
CONNECTION_STR: PostgresDsn | None = None
@validator('CONNECTION_STR', pre=True)
def build_connection_string(cls, v: str | None, values: dict[str, Any]) -> Any:
if isinstance(v, str):
return v
return PostgresDsn.build(
scheme="postgresql",
user=values.get('USER'),
password=values.get('PASSWORD'),
host=values.get('HOST'),
path=f'/{values.get("DATABASE", "")}',
)
class EmailConfig(BaseModel):
SMTP_TLS: bool = True
SMTP_PORT: int | None = None
SMTP_HOST: str | None = None
SMTP_USER: str | None = None
SMTP_PASSWORD: str | None = None
SENDER_ADDRESS: EmailStr | None = None
SENDER_NAME: str | None = 'NACSOS'
ENABLED: bool = False
@validator("ENABLED", pre=True)
def get_emails_enabled(cls, v: bool, values: dict[str, Any]) -> bool:
return bool(
values.get('SMTP_HOST')
and values.get('SMTP_PORT')
and values.get('SENDER_ADDRESS')
)
TEST_USER: EmailStr = EmailStr('test@nacsos.eu')
class UsersConfig(BaseModel):
# Set a valid user_id to skip authentication
# (should only be done in dev environment)
DEFAULT_USER: str | None = None
REGISTRATION_ENABLED: bool = False # Set this to true to enable the registration endpoint
class PipelinesConfig(BaseModel):
TOKEN: str
API_URL: str = 'http://localhost:8000/api'
USERNAME: str | None = None
USER_ID: str | None = None
class Settings(BaseSettings):
SERVER: ServerConfig = ServerConfig()
DB: DatabaseConfig = DatabaseConfig()
USERS: UsersConfig = UsersConfig()
PIPES: PipelinesConfig = PipelinesConfig()
# EMAIL: EmailConfig
LOG_CONF_FILE: str = 'config/logging.conf'
LOGGING_CONF: dict[str, Any] | None = None
@validator('LOGGING_CONF', pre=True)
def read_logging_config(cls, v: dict[str, Any] | None, values: dict[str, str]) -> dict[str, Any]:
if isinstance(v, dict):
return v
filename = values.get('LOG_CONF_FILE', None)
if filename is not None:
with open(filename, 'r') as f:
ret = toml.loads(f.read())
if type(ret) == dict:
return ret
raise ValueError('Logging config invalid!')
class Config:
case_sensitive = True
env_prefix = 'NACSOS_'
env_nested_delimiter = '__'
conf_file = os.environ.get('NACSOS_CONFIG', 'config/default.env')
settings = Settings(_env_file=conf_file, _env_file_encoding='utf-8')
__all__ = ['settings']