From 078ff189ac0346f1965d3e2d4f911c097d705a51 Mon Sep 17 00:00:00 2001 From: swve Date: Sat, 27 May 2023 22:08:21 +0200 Subject: [PATCH] feat: add cookie domain setting --- config/config.py | 142 +++++++++++++++++++++---------------------- config/config.yaml | 11 +--- docker-compose.yml | 2 + src/security/auth.py | 4 +- 4 files changed, 77 insertions(+), 82 deletions(-) diff --git a/config/config.py b/config/config.py index a5d215c2..f187fcc7 100644 --- a/config/config.py +++ b/config/config.py @@ -1,3 +1,4 @@ +from calendar import c from typing import Optional from pydantic import BaseModel import os @@ -10,23 +11,22 @@ class SentryConfig(BaseModel): release: str +class CookieConfig(BaseModel): + domain: str + + class HostingConfig(BaseModel): domain: str - port: int ssl: bool use_default_org: bool allowed_origins: list allowed_regexp: str self_hosted: bool sentry_config: Optional[SentryConfig] + cookie_config: CookieConfig class DatabaseConfig(BaseModel): - host: str - port: int - user: str - password: str - database_name: str mongodb_connection_string: Optional[str] @@ -39,108 +39,106 @@ class LearnHouseConfig(BaseModel): def get_learnhouse_config() -> LearnHouseConfig: - # Get the YAML file - yaml_path = os.path.join(os.path.dirname(__file__), 'config.yaml') + yaml_path = os.path.join(os.path.dirname(__file__), "config.yaml") # Load the YAML file - with open(yaml_path, 'r') as f: + with open(yaml_path, "r") as f: yaml_config = yaml.safe_load(f) - + # Check if environment variables are defined - env_site_name = os.environ.get('LEARNHOUSE_SITE_NAME') - env_site_description = os.environ.get('LEARNHOUSE_SITE_DESCRIPTION') - env_contact_email = os.environ.get('LEARNHOUSE_CONTACT_EMAIL') - env_domain = os.environ.get('LEARNHOUSE_DOMAIN') - env_port = os.environ.get('LEARNHOUSE_PORT') - env_ssl = os.environ.get('LEARNHOUSE_SSL') - env_use_default_org = os.environ.get('LEARNHOUSE_USE_DEFAULT_ORG') - env_allowed_origins = os.environ.get('LEARNHOUSE_ALLOWED_ORIGINS') + env_site_name = os.environ.get("LEARNHOUSE_SITE_NAME") + env_site_description = os.environ.get("LEARNHOUSE_SITE_DESCRIPTION") + env_contact_email = os.environ.get("LEARNHOUSE_CONTACT_EMAIL") + env_domain = os.environ.get("LEARNHOUSE_DOMAIN") + env_port = os.environ.get("LEARNHOUSE_PORT") + env_ssl = os.environ.get("LEARNHOUSE_SSL") + env_use_default_org = os.environ.get("LEARNHOUSE_USE_DEFAULT_ORG") + env_allowed_origins = os.environ.get("LEARNHOUSE_ALLOWED_ORIGINS") + env_cookie_domain = os.environ.get("LEARNHOUSE_COOKIE_DOMAIN") # Allowed origins should be a comma separated string if env_allowed_origins: - env_allowed_origins = env_allowed_origins.split(',') - env_allowed_regexp = os.environ.get('LEARNHOUSE_ALLOWED_REGEXP') - env_self_hosted = os.environ.get('LEARNHOUSE_SELF_HOSTED') - env_host = os.environ.get('LEARNHOUSE_DB_HOST') - env_db_port = os.environ.get('LEARNHOUSE_DB_PORT') - env_user = os.environ.get('LEARNHOUSE_DB_USER') - env_password = os.environ.get('LEARNHOUSE_DB_PASSWORD') - env_database_name = os.environ.get('LEARNHOUSE_DB_NAME') + env_allowed_origins = env_allowed_origins.split(",") + env_allowed_regexp = os.environ.get("LEARNHOUSE_ALLOWED_REGEXP") + env_self_hosted = os.environ.get("LEARNHOUSE_SELF_HOSTED") env_mongodb_connection_string = os.environ.get( - 'LEARNHOUSE_MONGODB_CONNECTION_STRING') + "LEARNHOUSE_MONGODB_CONNECTION_STRING" + ) # Sentry Config - env_sentry_dsn = os.environ.get('LEARNHOUSE_SENTRY_DSN') - env_sentry_environment = os.environ.get('LEARNHOUSE_SENTRY_ENVIRONMENT') - env_sentry_release = os.environ.get('LEARNHOUSE_SENTRY_RELEASE') + env_sentry_dsn = os.environ.get("LEARNHOUSE_SENTRY_DSN") + env_sentry_environment = os.environ.get("LEARNHOUSE_SENTRY_ENVIRONMENT") + env_sentry_release = os.environ.get("LEARNHOUSE_SENTRY_RELEASE") # Fill in values with YAML file if they are not provided - site_name = env_site_name or yaml_config.get('site_name') - site_description = env_site_description or yaml_config.get( - 'site_description') - contact_email = env_contact_email or yaml_config.get('contact_email') + site_name = env_site_name or yaml_config.get("site_name") + site_description = env_site_description or yaml_config.get("site_description") + contact_email = env_contact_email or yaml_config.get("contact_email") - domain = env_domain or yaml_config.get('hosting_config', {}).get('domain') - port = env_port or yaml_config.get('hosting_config', {}).get('port') - ssl = env_ssl or yaml_config.get('hosting_config', {}).get('ssl') - use_default_org = env_use_default_org or yaml_config.get( - 'hosting_config', {}).get('use_default_org') - allowed_origins = env_allowed_origins or yaml_config.get( - 'hosting_config', {}).get('allowed_origins') - allowed_regexp = env_allowed_regexp or yaml_config.get( - 'hosting_config', {}).get('allowed_regexp') - self_hosted = env_self_hosted or yaml_config.get( - 'hosting_config', {}).get('self_hosted') + domain = env_domain or yaml_config.get("hosting_config", {}).get("domain") + ssl = env_ssl or yaml_config.get("hosting_config", {}).get("ssl") + use_default_org = env_use_default_org or yaml_config.get("hosting_config", {}).get( + "use_default_org" + ) + allowed_origins = env_allowed_origins or yaml_config.get("hosting_config", {}).get( + "allowed_origins" + ) + allowed_regexp = env_allowed_regexp or yaml_config.get("hosting_config", {}).get( + "allowed_regexp" + ) + self_hosted = env_self_hosted or yaml_config.get("hosting_config", {}).get( + "self_hosted" + ) - host = env_host or yaml_config.get('database_config', {}).get('host') - db_port = env_db_port or yaml_config.get('database_config', {}).get('port') - user = env_user or yaml_config.get('database_config', {}).get('user') - password = env_password or yaml_config.get( - 'database_config', {}).get('password') - database_name = env_database_name or yaml_config.get( - 'database_config', {}).get('database_name') + cookies_domain = env_cookie_domain or yaml_config.get("hosting_config", {}).get("cookies_config", {}).get("domain") + cookie_config = CookieConfig( + domain=cookies_domain + ) + + # Database config mongodb_connection_string = env_mongodb_connection_string or yaml_config.get( - 'database_config', {}).get('mongodb_connection_string') + "database_config", {} + ).get("mongodb_connection_string") # Sentry config # check if the sentry config is provided in the YAML file - sentry_config_verif = yaml_config.get('hosting_config', {}).get('sentry_config') or env_sentry_dsn or env_sentry_environment or env_sentry_release or None + sentry_config_verif = ( + yaml_config.get("hosting_config", {}).get("sentry_config") + or env_sentry_dsn + or env_sentry_environment + or env_sentry_release + or None + ) - sentry_dsn = env_sentry_dsn or yaml_config.get( - 'hosting_config', {}).get('sentry_config', {}).get('dsn') + sentry_dsn = env_sentry_dsn or yaml_config.get("hosting_config", {}).get( + "sentry_config", {} + ).get("dsn") sentry_environment = env_sentry_environment or yaml_config.get( - 'hosting_config', {}).get('sentry_config', {}).get('environment') - sentry_release = env_sentry_release or yaml_config.get( - 'hosting_config', {}).get('sentry_config', {}).get('release') + "hosting_config", {} + ).get("sentry_config", {}).get("environment") + sentry_release = env_sentry_release or yaml_config.get("hosting_config", {}).get( + "sentry_config", {} + ).get("release") if sentry_config_verif: sentry_config = SentryConfig( - dsn=sentry_dsn, - environment=sentry_environment, - release=sentry_release + dsn=sentry_dsn, environment=sentry_environment, release=sentry_release ) else: sentry_config = None - - # Create HostingConfig and DatabaseConfig objects hosting_config = HostingConfig( domain=domain, - port=int(port), ssl=bool(ssl), use_default_org=bool(use_default_org), allowed_origins=list(allowed_origins), allowed_regexp=allowed_regexp, self_hosted=bool(self_hosted), - sentry_config=sentry_config + sentry_config=sentry_config, + cookie_config=cookie_config, ) database_config = DatabaseConfig( - host=host, - port=int(db_port), - user=user, - password=password, - database_name=database_name, mongodb_connection_string=mongodb_connection_string ) @@ -150,7 +148,7 @@ def get_learnhouse_config() -> LearnHouseConfig: site_description=site_description, contact_email=contact_email, hosting_config=hosting_config, - database_config=database_config + database_config=database_config, ) return config diff --git a/config/config.yaml b/config/config.yaml index 8e660a1e..3c848489 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -4,20 +4,13 @@ contact_email: hi@learnhouse.app hosting_config: domain: learnhouse.app - port: 443 ssl: true - use_default_org: false - default_org: learnhouse allowed_origins: - http://localhost:3000 - http://localhost:3001 + cookies_config: + domain: ".localhosst" allowed_regexp: '\b((?:https?://)[^\s/$.?#].[^\s]*)\b' - self_hosted: false database_config: - host: db.mongo - port: 5432 - user: myuser - password: mypassword - database_name: mydatabase mongodb_connection_string: mongodb://learnhouse:learnhouse@mongo:27017/ diff --git a/docker-compose.yml b/docker-compose.yml index 148e6b90..824cdc8d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,6 +6,8 @@ services: - "1338:80" volumes: - .:/usr/learnhouse + environment: + - LEARNHOUSE_COOKIE_DOMAIN=.localhost mongo: image: mongo:5.0 restart: always diff --git a/src/security/auth.py b/src/security/auth.py index be7d37b1..a4edaf49 100644 --- a/src/security/auth.py +++ b/src/security/auth.py @@ -1,3 +1,5 @@ +from webbrowser import get +from config.config import get_learnhouse_config from pydantic import BaseModel from fastapi import Depends, HTTPException, status from fastapi.security import OAuth2PasswordBearer @@ -19,7 +21,7 @@ class Settings(BaseModel): authjwt_access_token_expires = False # (pre-alpha only) # TODO: set to 1 hour authjwt_cookie_samesite = "lax" authjwt_cookie_secure = True - authjwt_cookie_domain = ".localhost" + authjwt_cookie_domain = get_learnhouse_config().hosting_config.cookie_config.domain @AuthJWT.load_config # type: ignore