Browse Source
* Use Pydantic BaseSettings for config settings * Update fastapi dep to >=0.47.0 and email_validator to email-validator * Fix deprecation warning for Pydantic >=1.0 * Properly support old-format comma separated strings for BACKEND_CORS_ORIGINS Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>pull/13907/head
committed by
GitHub
24 changed files with 173 additions and 140 deletions
@ -1,55 +1,92 @@ |
|||||
import os |
import os |
||||
|
import secrets |
||||
|
from typing import List |
||||
|
|
||||
|
from pydantic import AnyHttpUrl, BaseSettings, EmailStr, HttpUrl, PostgresDsn, validator |
||||
|
|
||||
def getenv_boolean(var_name, default_value=False): |
|
||||
result = default_value |
class Settings(BaseSettings): |
||||
env_value = os.getenv(var_name) |
|
||||
if env_value is not None: |
API_V1_STR: str = "/api/v1" |
||||
result = env_value.upper() in ("TRUE", "1") |
|
||||
return result |
SECRET_KEY: str = secrets.token_urlsafe(32) |
||||
|
|
||||
|
ACCESS_TOKEN_EXPIRE_MINUTES: int = 60 * 24 * 8 # 60 minutes * 24 hours * 8 days = 8 days |
||||
API_V1_STR = "/api/v1" |
|
||||
|
SERVER_NAME: str |
||||
SECRET_KEY = os.getenvb(b"SECRET_KEY") |
SERVER_HOST: AnyHttpUrl |
||||
if not SECRET_KEY: |
# BACKEND_CORS_ORIGINS is a JSON-formatted list of origins |
||||
SECRET_KEY = os.urandom(32) |
# e.g: '["http://localhost", "http://localhost:4200", "http://localhost:3000", \ |
||||
|
# "http://localhost:8080", "http://local.dockertoolbox.tiangolo.com"]' |
||||
ACCESS_TOKEN_EXPIRE_MINUTES = 60 * 24 * 8 # 60 minutes * 24 hours * 8 days = 8 days |
BACKEND_CORS_ORIGINS: List[AnyHttpUrl] = [] |
||||
|
|
||||
SERVER_NAME = os.getenv("SERVER_NAME") |
@validator("BACKEND_CORS_ORIGINS", pre=True) |
||||
SERVER_HOST = os.getenv("SERVER_HOST") |
def assemble_cors_origins(cls, v): |
||||
BACKEND_CORS_ORIGINS = os.getenv( |
if isinstance(v, str) and not v.startswith("["): |
||||
"BACKEND_CORS_ORIGINS" |
return [i.strip() for i in v.split(",")] |
||||
) # a string of origins separated by commas, e.g: "http://localhost, http://localhost:4200, http://localhost:3000, http://localhost:8080, http://local.dockertoolbox.tiangolo.com" |
return v |
||||
PROJECT_NAME = os.getenv("PROJECT_NAME") |
|
||||
SENTRY_DSN = os.getenv("SENTRY_DSN") |
PROJECT_NAME: str |
||||
|
SENTRY_DSN: HttpUrl = None |
||||
POSTGRES_SERVER = os.getenv("POSTGRES_SERVER") |
|
||||
POSTGRES_USER = os.getenv("POSTGRES_USER") |
@validator("SENTRY_DSN", pre=True) |
||||
POSTGRES_PASSWORD = os.getenv("POSTGRES_PASSWORD") |
def sentry_dsn_can_be_blank(cls, v): |
||||
POSTGRES_DB = os.getenv("POSTGRES_DB") |
if len(v) == 0: |
||||
SQLALCHEMY_DATABASE_URI = ( |
return None |
||||
f"postgresql://{POSTGRES_USER}:{POSTGRES_PASSWORD}@{POSTGRES_SERVER}/{POSTGRES_DB}" |
return v |
||||
) |
|
||||
|
POSTGRES_SERVER: str |
||||
SMTP_TLS = getenv_boolean("SMTP_TLS", True) |
POSTGRES_USER: str |
||||
SMTP_PORT = None |
POSTGRES_PASSWORD: str |
||||
_SMTP_PORT = os.getenv("SMTP_PORT") |
POSTGRES_DB: str |
||||
if _SMTP_PORT is not None: |
SQLALCHEMY_DATABASE_URI: PostgresDsn = None |
||||
SMTP_PORT = int(_SMTP_PORT) |
|
||||
SMTP_HOST = os.getenv("SMTP_HOST") |
@validator("SQLALCHEMY_DATABASE_URI", pre=True) |
||||
SMTP_USER = os.getenv("SMTP_USER") |
def assemble_db_connection(cls, v, values): |
||||
SMTP_PASSWORD = os.getenv("SMTP_PASSWORD") |
if isinstance(v, str): |
||||
EMAILS_FROM_EMAIL = os.getenv("EMAILS_FROM_EMAIL") |
return v |
||||
EMAILS_FROM_NAME = PROJECT_NAME |
return PostgresDsn.build( |
||||
EMAIL_RESET_TOKEN_EXPIRE_HOURS = 48 |
scheme="postgresql", |
||||
EMAIL_TEMPLATES_DIR = "/app/app/email-templates/build" |
user=values.get("POSTGRES_USER"), |
||||
EMAILS_ENABLED = SMTP_HOST and SMTP_PORT and EMAILS_FROM_EMAIL |
password=values.get("POSTGRES_PASSWORD"), |
||||
|
host=values.get("POSTGRES_SERVER"), |
||||
FIRST_SUPERUSER = os.getenv("FIRST_SUPERUSER") |
path=f"/{values.get('POSTGRES_DB') or ''}", |
||||
FIRST_SUPERUSER_PASSWORD = os.getenv("FIRST_SUPERUSER_PASSWORD") |
) |
||||
|
|
||||
USERS_OPEN_REGISTRATION = getenv_boolean("USERS_OPEN_REGISTRATION") |
SMTP_TLS: bool = True |
||||
|
SMTP_PORT: int = None |
||||
EMAIL_TEST_USER = "test@example.com" |
SMTP_HOST: str = None |
||||
|
SMTP_USER: str = None |
||||
|
SMTP_PASSWORD: str = None |
||||
|
EMAILS_FROM_EMAIL: EmailStr = None |
||||
|
EMAILS_FROM_NAME: str = None |
||||
|
|
||||
|
@validator("EMAILS_FROM_NAME") |
||||
|
def get_project_name(cls, v, values): |
||||
|
if not v: |
||||
|
return values["PROJECT_NAME"] |
||||
|
return v |
||||
|
|
||||
|
EMAIL_RESET_TOKEN_EXPIRE_HOURS: int = 48 |
||||
|
EMAIL_TEMPLATES_DIR: str = "/app/app/email-templates/build" |
||||
|
EMAILS_ENABLED: bool = False |
||||
|
|
||||
|
@validator("EMAILS_ENABLED", pre=True) |
||||
|
def get_emails_enabled(cls, v, values): |
||||
|
return bool( |
||||
|
values.get("SMTP_HOST") |
||||
|
and values.get("SMTP_PORT") |
||||
|
and values.get("EMAILS_FROM_EMAIL") |
||||
|
) |
||||
|
|
||||
|
EMAIL_TEST_USER: EmailStr = "test@example.com" |
||||
|
|
||||
|
FIRST_SUPERUSER: EmailStr |
||||
|
FIRST_SUPERUSER_PASSWORD: str |
||||
|
|
||||
|
USERS_OPEN_REGISTRATION: bool = False |
||||
|
|
||||
|
class Config: |
||||
|
case_sensitive = True |
||||
|
|
||||
|
settings = Settings() |
||||
|
Loading…
Reference in new issue