diff --git a/config/config.py b/config/config.py index 4b5de8bd..586e2945 100644 --- a/config/config.py +++ b/config/config.py @@ -1,3 +1,4 @@ +from gettext import install from typing import Literal, Optional from pydantic import BaseModel import os @@ -16,6 +17,7 @@ class CookieConfig(BaseModel): class GeneralConfig(BaseModel): development_mode: bool + install_mode: bool class SecurityConfig(BaseModel): @@ -71,6 +73,10 @@ def get_learnhouse_config() -> LearnHouseConfig: development_mode = env_development_mode or yaml_config.get("general", {}).get( "development_mode" ) + env_install_mode = os.environ.get("LEARNHOUSE_INSTALL_MODE") + install_mode = env_install_mode or yaml_config.get("general", {}).get( + "install_mode" + ) # Security Config env_auth_jwt_secret_key = os.environ.get("LEARNHOUSE_AUTH_JWT_SECRET_KEY") @@ -129,7 +135,7 @@ def get_learnhouse_config() -> LearnHouseConfig: env_content_delivery_type = os.environ.get("LEARNHOUSE_CONTENT_DELIVERY_TYPE") content_delivery_type: str = env_content_delivery_type or ( - (yaml_config.get("hosting_config", {}).get("content_delivery", {}).get("type")) + (yaml_config.get("hosting_config", {}).get("content_delivery", {}).get("type")) or "filesystem" ) # default to filesystem @@ -206,7 +212,9 @@ def get_learnhouse_config() -> LearnHouseConfig: site_name=site_name, site_description=site_description, contact_email=contact_email, - general_config=GeneralConfig(development_mode=bool(development_mode)), + general_config=GeneralConfig( + development_mode=bool(development_mode), install_mode=bool(install_mode) + ), hosting_config=hosting_config, database_config=database_config, security_config=SecurityConfig(auth_jwt_secret_key=auth_jwt_secret_key), diff --git a/config/config.yaml b/config/config.yaml index bf151243..12ee9e60 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -3,7 +3,8 @@ site_description: LearnHouse is an open-source platform tailored for learning ex contact_email: hi@learnhouse.app general: - development_mode: true + development_mode: false + install_mode: false security: auth_jwt_secret_key: secret diff --git a/front/middleware.ts b/front/middleware.ts index f784f958..ac547697 100644 --- a/front/middleware.ts +++ b/front/middleware.ts @@ -1,3 +1,4 @@ +import { isInstallModeEnabled } from "@services/install/install"; import { LEARNHOUSE_DOMAIN, getDefaultOrg, isMultiOrgModeEnabled } from "./services/config/config"; import { NextResponse } from "next/server"; import type { NextRequest } from "next/server"; @@ -16,7 +17,7 @@ export const config = { ], }; -export default function middleware(req: NextRequest) { +export default async function middleware(req: NextRequest) { // Get initial data const hosting_mode = isMultiOrgModeEnabled() ? "multi" : "single"; const default_org = getDefaultOrg(); @@ -30,7 +31,13 @@ export default function middleware(req: NextRequest) { // Install Page if (pathname.startsWith("/install")) { - return NextResponse.rewrite(new URL(pathname, req.url)); + // Check if install mode is enabled + const install_mode = await isInstallModeEnabled(); + if (install_mode) { + return NextResponse.rewrite(new URL(pathname, req.url)); + } else { + return NextResponse.redirect(new URL("/", req.url)); + } } // Dynamic Pages Editor diff --git a/front/services/install/install.ts b/front/services/install/install.ts index 445b2a04..ab69dc22 100644 --- a/front/services/install/install.ts +++ b/front/services/install/install.ts @@ -30,3 +30,13 @@ export async function createDefaultElements() { const res = await errorHandling(result); return res; } + +export async function isInstallModeEnabled() { + const result = await fetch(`${getAPIUrl()}install/latest`, RequestBody("GET", null, null)); + if (result.status === 200) { + return true; + } + else { + return false; + } +} diff --git a/src/router.py b/src/router.py index 2fd4f9d0..23e0c32b 100644 --- a/src/router.py +++ b/src/router.py @@ -2,7 +2,8 @@ from fastapi import APIRouter, Depends from src.routers import blocks, dev, trail, users, auth, orgs, roles from src.routers.courses import chapters, collections, courses, activities from src.routers.install import install -from src.services.dev.dev import isDevModeEnabled +from src.services.dev.dev import isDevModeEnabled, isDevModeEnabledOrRaise +from src.services.install.install import isInstallModeEnabled v1_router = APIRouter(prefix="/api/v1") @@ -17,13 +18,20 @@ v1_router.include_router(blocks.router, prefix="/blocks", tags=["blocks"]) v1_router.include_router(courses.router, prefix="/courses", tags=["courses"]) v1_router.include_router(chapters.router, prefix="/chapters", tags=["chapters"]) v1_router.include_router(activities.router, prefix="/activities", tags=["activities"]) -v1_router.include_router( collections.router, prefix="/collections", tags=["collections"]) +v1_router.include_router( + collections.router, prefix="/collections", tags=["collections"] +) v1_router.include_router(trail.router, prefix="/trail", tags=["trail"]) # Dev Routes v1_router.include_router( - dev.router, prefix="/dev", tags=["dev"], dependencies=[Depends(isDevModeEnabled)] + dev.router, prefix="/dev", tags=["dev"], dependencies=[Depends(isDevModeEnabledOrRaise)] ) # Install Routes -v1_router.include_router(install.router, prefix="/install", tags=["install"]) +v1_router.include_router( + install.router, + prefix="/install", + tags=["install"], + dependencies=[Depends(isInstallModeEnabled)], +) diff --git a/src/services/dev/dev.py b/src/services/dev/dev.py index 6c1e1879..53a51397 100644 --- a/src/services/dev/dev.py +++ b/src/services/dev/dev.py @@ -7,8 +7,12 @@ def isDevModeEnabled(): if config.general_config.development_mode: return True else: - raise HTTPException( - status_code=403, - detail="Development mode is not enabled", - ) + return False + +def isDevModeEnabledOrRaise(): + config = get_learnhouse_config() + if config.general_config.development_mode: + return True + else: + raise HTTPException(status_code=403, detail="Development mode is not enabled") diff --git a/src/services/install/install.py b/src/services/install/install.py index a80dfd50..e32b7185 100644 --- a/src/services/install/install.py +++ b/src/services/install/install.py @@ -3,6 +3,7 @@ from uuid import uuid4 from fastapi import HTTPException, Request, status from pydantic import BaseModel import requests +from config.config import get_learnhouse_config from src.security.security import security_hash_password from src.services.courses.activities.activities import Activity, create_activity from src.services.courses.chapters import create_coursechapter, CourseChapter @@ -31,6 +32,18 @@ class InstallInstance(BaseModel): data: dict +async def isInstallModeEnabled(): + config = get_learnhouse_config() + + if config.general_config.install_mode: + return True + else: + raise HTTPException( + status_code=403, + detail="Install mode is not enabled", + ) + + async def create_install_instance(request: Request, data: dict): installs = request.app.db["installs"] @@ -432,8 +445,6 @@ async def create_sample_data(org_slug: str, username: str, request: Request): courses = request.app.db["courses"] - - course = CourseInDB(**course.dict()) await courses.insert_one(course.dict())