mirror of
https://github.com/fastapi/full-stack-fastapi-template.git
synced 2026-09-23 06:10:54 +00:00
97 lines
2.9 KiB
Python
97 lines
2.9 KiB
Python
import warnings
|
|
from typing import Literal, Self
|
|
|
|
from pydantic import (
|
|
EmailStr,
|
|
HttpUrl,
|
|
PostgresDsn,
|
|
computed_field,
|
|
model_validator,
|
|
)
|
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
|
|
|
|
class Settings(BaseSettings):
|
|
model_config = SettingsConfigDict(
|
|
# Use top level .env file (one level above ./backend/)
|
|
env_file="../.env",
|
|
env_ignore_empty=True,
|
|
extra="ignore",
|
|
)
|
|
API_V1_STR: str = "/api/v1"
|
|
SECRET_KEY: str
|
|
# 60 minutes * 24 hours * 8 days = 8 days
|
|
ACCESS_TOKEN_EXPIRE_MINUTES: int = 60 * 24 * 8
|
|
FRONTEND_HOST: str = "http://localhost:5173"
|
|
FASTAPI_ENV: Literal["development"] | None = None
|
|
|
|
PROJECT_NAME: str
|
|
SENTRY_DSN: HttpUrl | None = None
|
|
POSTGRES_SERVER: str
|
|
POSTGRES_PORT: int = 5432
|
|
POSTGRES_USER: str
|
|
POSTGRES_PASSWORD: str = ""
|
|
POSTGRES_DB: str = ""
|
|
|
|
@computed_field # type: ignore[prop-decorator]
|
|
@property
|
|
def SQLALCHEMY_DATABASE_URI(self) -> PostgresDsn:
|
|
return PostgresDsn.build(
|
|
scheme="postgresql+psycopg",
|
|
username=self.POSTGRES_USER,
|
|
password=self.POSTGRES_PASSWORD,
|
|
host=self.POSTGRES_SERVER,
|
|
port=self.POSTGRES_PORT,
|
|
path=self.POSTGRES_DB,
|
|
)
|
|
|
|
SMTP_TLS: bool = True
|
|
SMTP_SSL: bool = False
|
|
SMTP_PORT: int = 587
|
|
SMTP_HOST: str | None = None
|
|
SMTP_USER: str | None = None
|
|
SMTP_PASSWORD: str | None = None
|
|
EMAILS_FROM_EMAIL: EmailStr | None = None
|
|
EMAILS_FROM_NAME: str | None = None
|
|
|
|
@model_validator(mode="after")
|
|
def _set_default_emails_from(self) -> Self:
|
|
if not self.EMAILS_FROM_NAME:
|
|
self.EMAILS_FROM_NAME = self.PROJECT_NAME
|
|
return self
|
|
|
|
EMAIL_RESET_TOKEN_EXPIRE_HOURS: int = 48
|
|
|
|
@computed_field # type: ignore[prop-decorator]
|
|
@property
|
|
def emails_enabled(self) -> bool:
|
|
return bool(self.SMTP_HOST and self.EMAILS_FROM_EMAIL)
|
|
|
|
EMAIL_TEST_USER: EmailStr = "test@example.com"
|
|
FIRST_SUPERUSER: EmailStr
|
|
FIRST_SUPERUSER_PASSWORD: str
|
|
|
|
def _check_default_secret(self, var_name: str, value: str | None) -> None:
|
|
if value == "changethis":
|
|
message = (
|
|
f'The value of {var_name} is "changethis", '
|
|
"for security, please change it, at least for deployments."
|
|
)
|
|
if self.FASTAPI_ENV == "development":
|
|
warnings.warn(message, stacklevel=1)
|
|
else:
|
|
raise ValueError(message)
|
|
|
|
@model_validator(mode="after")
|
|
def _enforce_non_default_secrets(self) -> Self:
|
|
self._check_default_secret("SECRET_KEY", self.SECRET_KEY)
|
|
self._check_default_secret("POSTGRES_PASSWORD", self.POSTGRES_PASSWORD)
|
|
self._check_default_secret(
|
|
"FIRST_SUPERUSER_PASSWORD", self.FIRST_SUPERUSER_PASSWORD
|
|
)
|
|
|
|
return self
|
|
|
|
|
|
settings = Settings() # type: ignore
|