|
|
|
@@ -1,18 +1,148 @@ |
|
|
|
#This file reads the .env where the variables should be stored |
|
|
|
import os |
|
|
|
import re |
|
|
|
from pathlib import Path |
|
|
|
from dotenv import load_dotenv |
|
|
|
|
|
|
|
load_dotenv() |
|
|
|
|
|
|
|
#Keycloak configuration (look in the .env) |
|
|
|
SECRET = os.getenv("SECRET") |
|
|
|
KEYCLOAK_AUDIENCE = os.getenv("KEYCLOAK_AUDIENCE") |
|
|
|
KEYCLOAK_SERVER = os.getenv("KEYCLOAK_SERVER") |
|
|
|
KEYCLOAK_ISSUER = os.getenv("KEYCLOAK_ISSUER") |
|
|
|
KEYCLOAK_PROTOCOL_ENDPOINT = os.getenv("KEYCLOAK_PROTOCOL_ENDPOINT") |
|
|
|
KEYCLOAK_JWKS_URL = os.getenv("KEYCLOAK_JWKS_URL") |
|
|
|
KEYCLOAK_AUTH_URL = os.getenv("KEYCLOAK_AUTH_URL") |
|
|
|
KEYCLOAK_TOKEN_URL = os.getenv("KEYCLOAK_TOKEN_URL") |
|
|
|
|
|
|
|
def _load_dotenv_chain() -> None: |
|
|
|
# Load local .env first |
|
|
|
load_dotenv(override=True) |
|
|
|
|
|
|
|
# Support shell-style source directives in .env, e.g. ". /data/conf/presence/core.conf" |
|
|
|
local_env = Path(".env") |
|
|
|
if not local_env.exists(): |
|
|
|
return |
|
|
|
|
|
|
|
for raw_line in local_env.read_text(encoding="utf-8").splitlines(): |
|
|
|
line = raw_line.strip() |
|
|
|
if not line or line.startswith("#"): |
|
|
|
continue |
|
|
|
if line.startswith(". "): |
|
|
|
target = line[2:].strip().strip('"').strip("'") |
|
|
|
elif line.startswith("source "): |
|
|
|
target = line[7:].strip().strip('"').strip("'") |
|
|
|
else: |
|
|
|
continue |
|
|
|
|
|
|
|
if not target: |
|
|
|
continue |
|
|
|
source_path = Path(target) |
|
|
|
if not source_path.is_absolute(): |
|
|
|
source_path = (local_env.parent / source_path).resolve() |
|
|
|
if source_path.exists(): |
|
|
|
load_dotenv(dotenv_path=source_path, override=True) |
|
|
|
|
|
|
|
# Safety fallback for deployments that keep Keycloak vars in core.conf. |
|
|
|
default_core_conf = Path("/data/conf/presence/core.conf") |
|
|
|
if default_core_conf.exists(): |
|
|
|
load_dotenv(dotenv_path=default_core_conf, override=True) |
|
|
|
|
|
|
|
|
|
|
|
_load_dotenv_chain() |
|
|
|
|
|
|
|
_SHELL_VAR_PATTERN = re.compile(r"\$\{([A-Za-z_][A-Za-z0-9_]*)\}|\$([A-Za-z_][A-Za-z0-9_]*)") |
|
|
|
|
|
|
|
|
|
|
|
def _clean(value: str) -> str: |
|
|
|
if value is None: |
|
|
|
return "" |
|
|
|
text = str(value).strip().strip('"').strip("'") |
|
|
|
if not text: |
|
|
|
return "" |
|
|
|
|
|
|
|
# Expand ${VAR} and $VAR references using already loaded environment variables. |
|
|
|
def _replace(match: re.Match) -> str: |
|
|
|
var_name = match.group(1) or match.group(2) |
|
|
|
return os.getenv(var_name, "") |
|
|
|
|
|
|
|
return _SHELL_VAR_PATTERN.sub(_replace, text) |
|
|
|
|
|
|
|
|
|
|
|
def _has_http_scheme(value: str) -> bool: |
|
|
|
return value.startswith("http://") or value.startswith("https://") |
|
|
|
|
|
|
|
|
|
|
|
def _ensure_http_scheme(value: str, default_scheme: str = "https") -> str: |
|
|
|
value = _clean(value) |
|
|
|
if not value: |
|
|
|
return "" |
|
|
|
if _has_http_scheme(value): |
|
|
|
return value |
|
|
|
if value.startswith("/"): |
|
|
|
return value |
|
|
|
return f"{default_scheme}://{value}" |
|
|
|
|
|
|
|
|
|
|
|
def _absolute_or_join(value: str, base_url: str) -> str: |
|
|
|
value = _clean(value) |
|
|
|
if not value: |
|
|
|
return "" |
|
|
|
if _has_http_scheme(value): |
|
|
|
return value |
|
|
|
if value.startswith("/"): |
|
|
|
if base_url: |
|
|
|
return f"{base_url.rstrip('/')}{value}" |
|
|
|
return "" |
|
|
|
return _ensure_http_scheme(value) |
|
|
|
|
|
|
|
|
|
|
|
def _env_first(*names: str) -> str: |
|
|
|
for name in names: |
|
|
|
value = _clean(os.getenv(name)) |
|
|
|
if value: |
|
|
|
return value |
|
|
|
return "" |
|
|
|
|
|
|
|
|
|
|
|
# Keycloak configuration (look in the .env) |
|
|
|
SECRET = _env_first("SECRET", "client_secret") |
|
|
|
KEYCLOAK_AUDIENCE = _env_first("KEYCLOAK_AUDIENCE", "keycloak_audience") |
|
|
|
|
|
|
|
_raw_keycloak_server = _env_first("KEYCLOAK_SERVER", "keycloak_server") |
|
|
|
KEYCLOAK_SERVER = _ensure_http_scheme(_raw_keycloak_server) |
|
|
|
|
|
|
|
_default_realm = _env_first("KEYCLOAK_REALM", "keycloak_realm") or "API.Server.local" |
|
|
|
|
|
|
|
_raw_keycloak_issuer = _env_first("KEYCLOAK_ISSUER", "keycloak_issuer") |
|
|
|
if _raw_keycloak_issuer and "${" not in _raw_keycloak_issuer: |
|
|
|
KEYCLOAK_ISSUER = _absolute_or_join(_raw_keycloak_issuer, KEYCLOAK_SERVER) |
|
|
|
elif KEYCLOAK_SERVER: |
|
|
|
KEYCLOAK_ISSUER = f"{KEYCLOAK_SERVER.rstrip('/')}/realms/{_default_realm}" |
|
|
|
else: |
|
|
|
KEYCLOAK_ISSUER = "" |
|
|
|
|
|
|
|
_raw_keycloak_protocol = _env_first("KEYCLOAK_PROTOCOL_ENDPOINT", "keycloak_protocol_endpoint") |
|
|
|
if _raw_keycloak_protocol and "${" not in _raw_keycloak_protocol: |
|
|
|
KEYCLOAK_PROTOCOL_ENDPOINT = _absolute_or_join(_raw_keycloak_protocol, KEYCLOAK_SERVER) |
|
|
|
elif KEYCLOAK_ISSUER: |
|
|
|
KEYCLOAK_PROTOCOL_ENDPOINT = f"{KEYCLOAK_ISSUER.rstrip('/')}/protocol/openid-connect" |
|
|
|
else: |
|
|
|
KEYCLOAK_PROTOCOL_ENDPOINT = "" |
|
|
|
|
|
|
|
_raw_jwks = _env_first("KEYCLOAK_JWKS_URL", "keycloak_jwks_url") |
|
|
|
if _raw_jwks and "${" not in _raw_jwks: |
|
|
|
KEYCLOAK_JWKS_URL = _absolute_or_join(_raw_jwks, KEYCLOAK_SERVER) |
|
|
|
elif KEYCLOAK_PROTOCOL_ENDPOINT: |
|
|
|
KEYCLOAK_JWKS_URL = f"{KEYCLOAK_PROTOCOL_ENDPOINT.rstrip('/')}/certs" |
|
|
|
else: |
|
|
|
KEYCLOAK_JWKS_URL = "" |
|
|
|
|
|
|
|
_raw_auth = _env_first("KEYCLOAK_AUTH_URL", "keycloak_auth_url") |
|
|
|
if _raw_auth and "${" not in _raw_auth: |
|
|
|
KEYCLOAK_AUTH_URL = _absolute_or_join(_raw_auth, KEYCLOAK_SERVER) |
|
|
|
elif KEYCLOAK_PROTOCOL_ENDPOINT: |
|
|
|
KEYCLOAK_AUTH_URL = f"{KEYCLOAK_PROTOCOL_ENDPOINT.rstrip('/')}/auth" |
|
|
|
else: |
|
|
|
KEYCLOAK_AUTH_URL = "" |
|
|
|
|
|
|
|
_raw_token = _env_first("KEYCLOAK_TOKEN_URL", "keycloak_token_url") |
|
|
|
if _raw_token and "${" not in _raw_token: |
|
|
|
KEYCLOAK_TOKEN_URL = _absolute_or_join(_raw_token, KEYCLOAK_SERVER) |
|
|
|
elif KEYCLOAK_PROTOCOL_ENDPOINT: |
|
|
|
KEYCLOAK_TOKEN_URL = f"{KEYCLOAK_PROTOCOL_ENDPOINT.rstrip('/')}/token" |
|
|
|
else: |
|
|
|
KEYCLOAK_TOKEN_URL = "" |
|
|
|
|
|
|
|
CORE_API_URL = os.getenv("CORE_API_URL", "http://localhost:1902") |
|
|
|
|
|
|
|
MQTT_HOST = os.getenv("MQTT_HOST", "192.168.1.101") |
|
|
|
@@ -32,3 +162,8 @@ BLE_AI_META_DIR = os.getenv( |
|
|
|
"/data/service/ble-ai-localizer/data/maps/", |
|
|
|
) |
|
|
|
|
|
|
|
BLE_AI_MAPS_DIR = os.getenv( |
|
|
|
"BLE_AI_MAPS_DIR", |
|
|
|
"/data/service/ble-ai-localizer/data/maps", |
|
|
|
) |
|
|
|
|