config.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  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. # PROJECT NAME, VERSION AND DESCRIPTION
  36. PROJECT_NAME: str = PYPROJECT_CONTENT["name"]
  37. VERSION: str = PYPROJECT_CONTENT["version"]
  38. DESCRIPTION: str = PYPROJECT_CONTENT["description"]
  39. # POSTGRESQL DEFAULT DATABASE
  40. DEFAULT_DATABASE_HOSTNAME: str
  41. DEFAULT_DATABASE_USER: str
  42. DEFAULT_DATABASE_PASSWORD: str
  43. DEFAULT_DATABASE_PORT: str
  44. DEFAULT_DATABASE_DB: str
  45. @property
  46. def DEFAULT_SQLALCHEMY_DATABASE_URI(self) -> str:
  47. return build_postgreuri(
  48. scheme="postgresql",
  49. username=self.DEFAULT_DATABASE_USER,
  50. password=self.DEFAULT_DATABASE_PASSWORD,
  51. host=self.DEFAULT_DATABASE_HOSTNAME,
  52. port=int(self.DEFAULT_DATABASE_PORT),
  53. path=f"/{self.DEFAULT_DATABASE_DB}",
  54. )
  55. # POSTGRESQL TEST DATABASE
  56. TEST_DATABASE_HOSTNAME: str = "postgres"
  57. TEST_DATABASE_USER: str = "postgres"
  58. TEST_DATABASE_PASSWORD: str = "postgres"
  59. TEST_DATABASE_PORT: str = "5432"
  60. TEST_DATABASE_DB: str = "postgres"
  61. @property
  62. def TEST_SQLALCHEMY_DATABASE_URI(self) -> str:
  63. return build_postgreuri(
  64. scheme="postgresql",
  65. username=self.TEST_DATABASE_USER,
  66. password=self.TEST_DATABASE_PASSWORD,
  67. host=self.TEST_DATABASE_HOSTNAME,
  68. port=int(self.TEST_DATABASE_PORT),
  69. path=f"/{self.TEST_DATABASE_DB}",
  70. )
  71. # SMS batch
  72. BATCH_SMS_PHONE_NUMBER: str = ""
  73. # FIRST SUPERUSER
  74. FIRST_SUPERUSER_EMAIL: EmailStr
  75. FIRST_SUPERUSER_PASSWORD: str
  76. model_config = SettingsConfigDict(
  77. env_file=f"{PROJECT_DIR}/.env", case_sensitive=True
  78. )
  79. settings: Settings = Settings() # type: ignore