init commit

This commit is contained in:
2026-05-11 12:15:03 +03:00
commit 7dbbd98312
96 changed files with 3750 additions and 0 deletions

View File

@@ -0,0 +1,132 @@
from functools import lru_cache
import json
from typing import Any
from pydantic import Field,PrivateAttr
from pydantic_settings import BaseSettings,SettingsConfigDict
from src.infrastructure.vault import VaultClient
class Settings(BaseSettings):
model_config = SettingsConfigDict(env_file='.env',extra='ignore')
_vault_beorg_secrets: dict[str,Any] = PrivateAttr(default_factory=dict)
DOCS_USERNAME: str = 'admin'
DOCS_PASSWORD: str = 'admin'
KEYDB_URL: str = 'redis://localhost:6379/0'
VAULT_ADDR: str = 'https://corp.vault.elcsa.ru'
VAULT_ROLE_ID: str = ''
VAULT_SECRET_ID: str = ''
VAULT_NAMESPACE: str | None = None
VAULT_MOUNT_POINT: str = 'dev-secrets'
VAULT_APP_SECRET_PATH: str = 'app'
VAULT_BEORG_SECRET_PATH: str = 'beorg'
VAULT_DATABASE_SECRET_PATH: str = 'database'
VAULT_JWT_SECRET_PATH: str = 'jwt'
VAULT_RABBIT_SECRET_PATH: str = 'rabbitmq'
VAULT_DOCS_SECRET_PATH: str = 'docs'
VAULT_JWT_KID_PATH: str = 'jwt/kid'
VAULT_JWT_KIDS_PREFIX: str = 'jwt/kids'
JWT_KEYS_REFRESH_SECONDS: int = 300
JWT_ALGORITHM: str = 'RS256'
JWT_AUDIENCE: str | None = None
JWT_ISSUER: str | None = None
RABBIT_URL: str = 'amqp://guest:guest@localhost:5672/'
RABBIT_CRYPTO_TRANSFER_COMPLETED_QUEUE: str = 'crypto_transfer_completed'
RABBIT_KYC_VERIFIED_QUEUE: str = 'kyc_verified'
RABBIT_PUBLISH_PERSIST: bool = True
DATABASE_URL: str = 'postgresql+asyncpg://postgres:postgres@localhost:5432/kyc'
DATABASE_POOL_SIZE: int = 5
DATABASE_MAX_OVERFLOW: int = 10
DATABASE_POOL_TIMEOUT: int = 30
DATABASE_POOL_RECYCLE: int = 1800
DATABASE_ECHO: bool = False
EXCLUDED_PATHS: tuple[str,...] = ('/docs','/redoc','/openapi.json','/ping')
BEORG_TIMEOUT: int = 15
BEORG_PROCESS_INFO: list[dict[str,Any]] = Field(default_factory=lambda: [
{
'key': 'SELFIE1',
'type': 'SELFIE',
'options': {
'stages': [
'biometry_liveness',
],
},
'attempts': 3,
},
{
'key': 'PASSPORT1',
'type': 'PASSPORT',
'options': {
'stages': [
'verification',
'biometry_match',
],
'relation': {
'biometry_match': 'SELFIE1',
},
},
'attempts': 3,
},
])
@property
def BEORG_PROJECT_ID(self) -> str:
return self._get_beorg_secret('project_id','BEORG_PROJECT_ID')
@property
def BEORG_MACHINE_UID(self) -> str:
return self._get_beorg_secret('machine_uid','BEORG_MACHINE_UID')
@property
def BEORG_TOKEN(self) -> str:
return self._get_beorg_secret('token','BEORG_TOKEN')
def _get_beorg_secret(self,*keys: str) -> str:
for key in keys:
value = self._vault_beorg_secrets.get(key)
if value is not None:
return str(value)
return ''
def model_post_init(self,__context: Any) -> None:
if not self.VAULT_ROLE_ID or not self.VAULT_SECRET_ID:
return
client = VaultClient(
addr=self.VAULT_ADDR,
role_id=self.VAULT_ROLE_ID,
secret_id=self.VAULT_SECRET_ID,
namespace=self.VAULT_NAMESPACE,
mount_point=self.VAULT_MOUNT_POINT,
)
object.__setattr__(self,'_vault_beorg_secrets',client.read_many(self.VAULT_BEORG_SECRET_PATH))
secrets = client.read_many(
self.VAULT_APP_SECRET_PATH,
self.VAULT_BEORG_SECRET_PATH,
self.VAULT_DATABASE_SECRET_PATH,
self.VAULT_JWT_SECRET_PATH,
self.VAULT_RABBIT_SECRET_PATH,
self.VAULT_DOCS_SECRET_PATH,
)
for field in type(self).model_fields:
if field.startswith('VAULT_') or field == 'KEYDB_URL':
continue
value = secrets.get(field,secrets.get(field.lower()))
if value is None:
continue
if field == 'BEORG_PROCESS_INFO' and isinstance(value,str):
value = json.loads(value)
object.__setattr__(self,field,value)
@lru_cache
def get_settings() -> Settings:
return Settings()
settings = get_settings()