config.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. """
  2. File with environment variables and general configuration logic.
  3. `SECRET_KEY`, `ENVIRONMENT` etc. map to env variables with the same names.
  4. Pydantic priority ordering:
  5. 1. (Most important, will overwrite everything) - environment variables
  6. 2. `.env` file in root folder of project
  7. 3. Default values
  8. For project name, version, description we use pyproject.toml
  9. For the rest, we use file `.env` (gitignored), see `.env.example`
  10. See https://pydantic-docs.helpmanual.io/usage/settings/
  11. Note, complex types like lists are read as json-encoded strings.
  12. """
  13. import tomllib
  14. from pathlib import Path
  15. from typing import Literal
  16. from pydantic import AnyHttpUrl, EmailStr
  17. from pydantic_settings import BaseSettings, SettingsConfigDict
  18. PROJECT_DIR = Path(__file__).parent.parent.parent
  19. with open(f"{PROJECT_DIR}/pyproject.toml", "rb") as f:
  20. PYPROJECT_CONTENT = tomllib.load(f)["tool"]["poetry"]
  21. def build_postgreuri(
  22. scheme: str, username: str, password: str, host: str, port: int = 0, path: str = ""
  23. ):
  24. fullhost = host + (f":{port}" if port > 0 else "")
  25. return f"{scheme}://{username}:{password}@{fullhost}{path}"
  26. class Settings(BaseSettings):
  27. # CORE SETTINGS
  28. SECRET_KEY: str
  29. ENVIRONMENT: Literal["DEV", "PYTEST", "STG", "PRD"] = "DEV"
  30. SECURITY_BCRYPT_ROUNDS: int = 12
  31. ACCESS_TOKEN_EXPIRE_MINUTES: int = 11520 # 8 days
  32. REFRESH_TOKEN_EXPIRE_MINUTES: int = 40320 # 28 days
  33. BACKEND_CORS_ORIGINS: list[AnyHttpUrl | Literal["*"]] = []
  34. ALLOWED_HOSTS: list[str] = ["localhost", "127.0.0.1"]
  35. INACTIVITY_SMS_SENDER_THRESHOLD_SECONDS:int = 180
  36. # PROJECT NAME, VERSION AND DESCRIPTION
  37. PROJECT_NAME: str = PYPROJECT_CONTENT["name"]
  38. VERSION: str = PYPROJECT_CONTENT["version"]
  39. DESCRIPTION: str = PYPROJECT_CONTENT["description"]
  40. # POSTGRESQL DEFAULT DATABASE
  41. DEFAULT_DATABASE_HOSTNAME: str
  42. DEFAULT_DATABASE_USER: str
  43. DEFAULT_DATABASE_PASSWORD: str
  44. DEFAULT_DATABASE_PORT: str
  45. DEFAULT_DATABASE_DB: str
  46. @property
  47. def DEFAULT_SQLALCHEMY_DATABASE_URI(self) -> str:
  48. return build_postgreuri(
  49. scheme="postgresql",
  50. username=self.DEFAULT_DATABASE_USER,
  51. password=self.DEFAULT_DATABASE_PASSWORD,
  52. host=self.DEFAULT_DATABASE_HOSTNAME,
  53. port=int(self.DEFAULT_DATABASE_PORT),
  54. path=f"/{self.DEFAULT_DATABASE_DB}",
  55. )
  56. # POSTGRESQL TEST DATABASE
  57. TEST_DATABASE_HOSTNAME: str = "postgres"
  58. TEST_DATABASE_USER: str = "postgres"
  59. TEST_DATABASE_PASSWORD: str = "postgres"
  60. TEST_DATABASE_PORT: str = "5432"
  61. TEST_DATABASE_DB: str = "postgres"
  62. @property
  63. def TEST_SQLALCHEMY_DATABASE_URI(self) -> str:
  64. return build_postgreuri(
  65. scheme="postgresql",
  66. username=self.TEST_DATABASE_USER,
  67. password=self.TEST_DATABASE_PASSWORD,
  68. host=self.TEST_DATABASE_HOSTNAME,
  69. port=int(self.TEST_DATABASE_PORT),
  70. path=f"/{self.TEST_DATABASE_DB}",
  71. )
  72. # SMS batch
  73. BATCH_SMS_PHONE_NUMBER: str = ""
  74. # FIRST SUPERUSER
  75. FIRST_SUPERUSER_EMAIL: EmailStr
  76. FIRST_SUPERUSER_PASSWORD: str
  77. model_config = SettingsConfigDict(env_file=f"{PROJECT_DIR}/.env", case_sensitive=True)
  78. settings: Settings = Settings() # type: ignore