diff --git a/app.py b/app.py index c4f356a2..f62b2bba 100644 --- a/app.py +++ b/app.py @@ -1,6 +1,8 @@ +import asyncio import logging from fastapi import FastAPI, Request import re +from config.config import LearnHouseConfig, get_learnhouse_config from src.core.config.config import Settings, get_settings from src.core.events.events import shutdown_app, startup_app from src.main import global_router @@ -16,10 +18,13 @@ from fastapi_jwt_auth.exceptions import AuthJWTException # (c) LearnHouse 2022 ######################## +# Get LearnHouse Config +learnhouse_config: LearnHouseConfig = get_learnhouse_config() + # Global Config app = FastAPI( - title="LearnHouse", - description="LearnHouse is a new open-source platform tailored for learning experiences.", + title=learnhouse_config.site_name, + description=learnhouse_config.site_description, version="0.1.0", root_path="/" ) @@ -45,7 +50,7 @@ app.add_event_handler("shutdown", shutdown_app(app)) # JWT Exception Handler -@app.exception_handler(AuthJWTException) +@ app.exception_handler(AuthJWTException) def authjwt_exception_handler(request: Request, exc: AuthJWTException): return JSONResponse( status_code=exc.status_code, # type: ignore @@ -59,10 +64,19 @@ app.include_router(global_router) # General Routes -@app.get("/") +@ app.get("/") async def root(): return {"Message": "Welcome to LearnHouse ✨"} +# Get config + + +@ app.get("/config") +async def config(): + logging.info("Getting config") + config = get_learnhouse_config() + return config.dict() + # @app.get("/initial_data") # async def initial_data(request: Request): diff --git a/config/config.py b/config/config.py index e69de29b..e94ae341 100644 --- a/config/config.py +++ b/config/config.py @@ -0,0 +1,111 @@ +from pydantic import BaseModel +import os +import yaml + + +class HostingConfig(BaseModel): + domain: str + port: int + ssl: bool + use_default_org: bool + allowed_origins: list + allowed_regexp: str + self_hosted: bool + + +class DatabaseConfig(BaseModel): + host: str + port: int + user: str + password: str + database_name: str + + +class LearnHouseConfig(BaseModel): + site_name: str + site_description: str + contact_email: str + hosting_config: HostingConfig + database_config: DatabaseConfig + + +def get_learnhouse_config() -> LearnHouseConfig: + + # Get the YAML file + yaml_path = os.path.join(os.path.dirname(__file__), 'config.yaml') + + # Load the YAML file + 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_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') + + # 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') + + 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') + + 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') + + # 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) + ) + database_config = DatabaseConfig( + host=host, + port=int(db_port), + user=user, + password=password, + database_name=database_name + ) + + # Create LearnHouseConfig object + config = LearnHouseConfig( + site_name=site_name, + site_description=site_description, + contact_email=contact_email, + hosting_config=hosting_config, + database_config=database_config + ) + + return config diff --git a/config/config.yaml b/config/config.yaml new file mode 100644 index 00000000..242fb31c --- /dev/null +++ b/config/config.yaml @@ -0,0 +1,21 @@ +site_name: LearnHouse +site_description: LearnHouse is an open-source platform tailored for learning experiences. +contact_email: hi@learnhouse.app + +hosting_config: + domain: learnhouse.app + port: 443 + ssl: true + use_default_org: false + allowed_origins: + - https://learnhouse.app + - https://learnhouse.io + allowed_regexp: "^https://(.*\\.)?learnhouse\\.app$" + self_hosted: false + +database_config: + host: db.mongo + port: 5432 + user: myuser + password: mypassword + database_name: mydatabase diff --git a/config/config.yml b/config/config.yml deleted file mode 100644 index e69de29b..00000000 diff --git a/front/tsconfig.json b/front/tsconfig.json index 31ffef7d..e8fc70c6 100644 --- a/front/tsconfig.json +++ b/front/tsconfig.json @@ -29,7 +29,7 @@ "@editor/*": ["components/Editor/*"] } }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx","**/**/*.tsx", ".next/types/**/*.ts"], "exclude": ["node_modules"] } diff --git a/requirements.txt b/requirements.txt index d1f1bd3a..b6abfd01 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,4 +8,5 @@ python-jose passlib fastapi-jwt-auth faker -requests \ No newline at end of file +requests +pyyaml \ No newline at end of file diff --git a/src/core/events/events.py b/src/core/events/events.py index daa8cc01..27dd830b 100644 --- a/src/core/events/events.py +++ b/src/core/events/events.py @@ -1,6 +1,7 @@ from typing import Callable from fastapi import FastAPI from src.core.events.database import close_database, connect_to_db +from src.core.events.logs import create_logs_dir def startup_app(app: FastAPI) -> Callable: @@ -8,6 +9,9 @@ def startup_app(app: FastAPI) -> Callable: # Connect to database await connect_to_db(app) + # Create logs directory + await create_logs_dir() + return start_app diff --git a/src/core/events/logs.py b/src/core/events/logs.py new file mode 100644 index 00000000..08550073 --- /dev/null +++ b/src/core/events/logs.py @@ -0,0 +1,24 @@ +import logging +import os + + +async def create_logs_dir(): + if not os.path.exists("logs"): + os.mkdir("logs") + +# Initiate logging +async def init_logging(): + await create_logs_dir() + + # Logging + logging.basicConfig( + level=logging.INFO, + format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", + datefmt="%d-%b-%y %H:%M:%S", + handlers=[ + logging.FileHandler("logs/learnhouse.log"), + logging.StreamHandler() + ] + ) + + logging.info("Logging initiated")