11import os
2+ import warnings
23from enum import Enum
4+ from typing import Self
35
4- from pydantic import SecretStr , computed_field , field_validator
6+ from pydantic import SecretStr , computed_field , field_validator , model_validator
57from pydantic_settings import BaseSettings , SettingsConfigDict
68
79
@@ -20,7 +22,7 @@ class AppSettings(BaseSettings):
2022 def validate_hosts (cls , host : str ) -> str :
2123 if host is not None and not (host .startswith ("http://" ) or host .startswith ("https://" )):
2224 raise ValueError (
23- f"HOSTS must define their protocol and start with http:// or https://. Received the host { host } ."
25+ f"HOSTS must define their protocol and start with http:// or https://. Received the host ' { host } ' ."
2426 )
2527 return host
2628
@@ -183,14 +185,28 @@ class Settings(
183185 extra = "ignore" ,
184186 )
185187
186- @field_validator ("APP_FRONTEND_HOST" )
187- @classmethod
188- def validate_app_frontend_host_protocol (cls , host : str ) -> str :
189- if EnvironmentSettings .ENVIRONMENT == EnvironmentOption .PRODUCTION and not host .startswith ("https://" ):
190- raise ValueError (
191- f"In production, APP_FRONTEND_HOST must start with the https:// protocol. Received the host { host } ."
192- )
193- return host
188+ @model_validator (mode = "after" )
189+ def validate_environment_settings (self ) -> Self :
190+ if self .ENVIRONMENT == EnvironmentOption .LOCAL :
191+ pass
192+ elif self .ENVIRONMENT == EnvironmentOption .STAGING :
193+ if "*" in self .CORS_ORIGINS :
194+ warnings .warn (
195+ "For security, in a staging environment CORS_ORIGINS should not include '*'. "
196+ "It's recommended to specify explicit origins (e.g., ['https://staging.example.com'])."
197+ )
198+ elif self .ENVIRONMENT == EnvironmentOption .PRODUCTION :
199+ if "*" in self .CORS_ORIGINS :
200+ raise ValueError (
201+ "For security, in a production environment CORS_ORIGINS cannot include '*'. "
202+ "You must specify explicit allowed origins (e.g., ['https://example.com', 'https://www.example.com'])."
203+ )
204+ if self .APP_FRONTEND_HOST and not self .APP_FRONTEND_HOST .startswith ("https://" ):
205+ raise ValueError (
206+ "In production, APP_FRONTEND_HOST must start with the https:// protocol. "
207+ f"Received the host '{ self .APP_FRONTEND_HOST } '."
208+ )
209+ return self
194210
195211
196212settings = Settings ()
0 commit comments