### Frontend Local Development Setup Source: https://github.com/xnicolas99/yachtplus/blob/master/README.md Steps to set up the Node.js frontend environment for local development. Includes installing dependencies and starting the Vite development server. ```bash cd frontend npm install npm run dev # Vite dev server on :8080, proxies /api → :8000 ``` -------------------------------- ### Backend Local Development Setup Source: https://github.com/xnicolas99/yachtplus/blob/master/README.md Steps to set up the Python backend environment for local development. Includes virtual environment activation, dependency installation, and running the Uvicorn server. ```bash cd backend python -m venv .venv && source .venv/bin/activate # Linux/macOS # .\.venv\Scripts\Activate.ps1 # Windows / PowerShell pip install -r requirements.txt # On Windows, uvloop is not supported — strip that line first: # pip install -r <(grep -v '^uvloop' requirements.txt) # Backend listens on :8000 uvicorn api.main:app --reload --port 8000 ``` -------------------------------- ### Installing Frontend Dependencies and Running Development Server Source: https://github.com/xnicolas99/yachtplus/blob/master/AGENTS.md Installs frontend dependencies using npm and starts the development server with Vite. The server runs on port 8080 and proxies API requests to port 8000. ```bash cd frontend npm install npm run dev # Vite on :8080, proxies /api → :8000 ``` -------------------------------- ### Start Development Server Source: https://github.com/xnicolas99/yachtplus/blob/master/frontend/README.md Use this command to compile and start the development server with hot-reloading. ```bash npm run serve ``` -------------------------------- ### Install Project Dependencies Source: https://github.com/xnicolas99/yachtplus/blob/master/frontend/README.md Run this command to install all necessary project dependencies. ```bash npm install ``` -------------------------------- ### Finalize Setup Source: https://github.com/xnicolas99/yachtplus/blob/master/README.md Completes the initial setup process. This endpoint verifies that 2FA is enabled, marks the setup as complete, and issues a fresh JWT without the `setup_pending` claim. ```APIDOC ## POST /api/setup/finalize ### Description Verifies 2FA is enabled, marks setup complete, and issues a fresh token without `setup_pending`. ### Method POST ### Endpoint /api/setup/finalize ``` -------------------------------- ### Start Yachtplus Docker Container Source: https://github.com/xnicolas99/yachtplus/blob/master/README.md Command to start the Yachtplus service in detached mode. Access the setup wizard via the specified host and port. ```bash docker-compose up -d # → open http://:8000 and run through the setup wizard ``` -------------------------------- ### Setting up Python Virtual Environment and Installing Dependencies Source: https://github.com/xnicolas99/yachtplus/blob/master/AGENTS.md This snippet demonstrates how to create a Python virtual environment and install project dependencies using pip. It includes a workaround for Windows users encountering issues with the 'uvloop' package. ```bash cd backend python -m venv .venv && source .venv/bin/activate # or .venv\Scripts\Activate.ps1 on Windows pip install -r requirements.txt # On Windows: uvloop has no wheels. Skip it: # grep -v '^uvloop' requirements.txt > /tmp/req && pip install -r /tmp/req ``` -------------------------------- ### Setup Status Check Source: https://github.com/xnicolas99/yachtplus/blob/master/README.md Checks if the initial setup is required for the YachtPlus instance. This is typically the first call made by the frontend. ```APIDOC ## GET /api/setup/status ### Description Frontend checks if first-time setup is required. ### Method GET ### Endpoint /api/setup/status ``` -------------------------------- ### Setup Status Check API Endpoint Source: https://github.com/xnicolas99/yachtplus/blob/master/README.md Frontend endpoint to check if the initial setup is required for a new YachtPlus instance. ```http GET /api/setup/status ``` -------------------------------- ### Auth Check Middleware Example Source: https://github.com/xnicolas99/yachtplus/blob/master/AGENTS.md Illustrates the use of `auth_check` and `auth_check_setup_pending` for token validation in FastAPI endpoints. `auth_check` is for general data routes, while `auth_check_setup_pending` is for setup or 2FA related routes. ```python # backend/api/auth/auth.py: auth_check # backend/api/auth/auth.py: auth_check_setup_pending # Example usage in an endpoint: # from backend.api.auth.auth import auth_check, auth_check_setup_pending # from fastapi import Depends # @router.get("/data") # async def get_data(Authorize: Authorize = Depends(auth_check)): # # ... endpoint logic ... # pass # @router.post("/setup/finalize") # async def finalize_setup( # Authorize: Authorize = Depends(auth_check_setup_pending), # db: AsyncSession = Depends(get_db), # ): # # ... setup finalization logic ... # pass ``` -------------------------------- ### Finalize Setup API Endpoint Source: https://github.com/xnicolas99/yachtplus/blob/master/README.md Endpoint to complete the initial setup process, verifying 2FA and issuing a fresh, non-setup-pending token. ```http POST /api/setup/finalize ``` -------------------------------- ### 2FA Enforcement in Setup Finalization Source: https://github.com/xnicolas99/yachtplus/blob/master/README.md Ensures that the setup finalization process rejects accounts that have not enabled Two-Factor Authentication. ```python /finalize rejects accounts without 2FA. ``` -------------------------------- ### Running Backend Development Server Source: https://github.com/xnicolas99/yachtplus/blob/master/AGENTS.md Starts the backend API server using uvicorn for development. It requires setting the DATABASE_URL environment variable and specifies the port to run on. ```bash export DATABASE_URL="sqlite:///./local.db" # avoid /config/yacht.db uvicorn api.main:app --reload --port 8000 ``` -------------------------------- ### Clean Rebuild: Pull and Start Source: https://github.com/xnicolas99/yachtplus/blob/master/DEBUGGING_CHEATSHEET.md After stopping containers, removing the image, and pruning volumes, pull the latest images and start the services in detached mode. ```bash docker-compose pull docker-compose up -d ``` -------------------------------- ### Permission Check Example Source: https://github.com/xnicolas99/yachtplus/blob/master/AGENTS.md Demonstrates how to implement fine-grained access control using `check_permission` for specific user actions beyond basic authentication. ```python # backend/api/auth/auth.py: check_permission # Example usage in an endpoint: # from backend.api.auth.auth import auth_check, check_permission # from fastapi import Depends # @router.post("/resource/{resource_id}/action") # async def perform_action( # resource_id: int, # Authorize: Authorize = Depends(auth_check), # db: AsyncSession = Depends(get_db), # ): # await check_permission("perm_perform_action", Authorize, db) # # ... perform action logic ... # pass ``` -------------------------------- ### Register Initial Admin User API Endpoint Source: https://github.com/xnicolas99/yachtplus/blob/master/README.md API endpoint to create the first administrator user. It issues a short-lived JWT with a setup pending claim. ```http POST /api/setup/register ``` -------------------------------- ### Generate 2FA Secret Source: https://github.com/xnicolas99/yachtplus/blob/master/README.md Generates a Time-based One-Time Password (TOTP) secret for Two-Factor Authentication. This is part of the initial setup flow. ```APIDOC ## POST /api/auth/2fa/generate ### Description Generates a TOTP QR code and secret for Two-Factor Authentication setup. Accepts `setup_pending=True` tokens. ### Method POST ### Endpoint /api/auth/2fa/generate ``` -------------------------------- ### Docker Compose for Fail2Ban Sidecar Source: https://github.com/xnicolas99/yachtplus/blob/master/fail2ban/README.md Configure Fail2Ban as a Docker sidecar service in your docker-compose.yml. This setup requires host networking and specific capabilities for Fail2Ban to manage network rules. ```yaml services: fail2ban: image: crazymax/fail2ban:latest network_mode: "host" cap_add: - NET_ADMIN - NET_RAW volumes: - ./fail2ban/filter.d:/etc/fail2ban/filter.d:ro - ./fail2ban/jail.local:/etc/fail2ban/jail.d/yachtplus.local:ro - /var/log:/var/log:ro # Map where your logs are - /var/run/docker.sock:/var/run/docker.sock:ro ``` -------------------------------- ### Generate 2FA TOTP Secret API Endpoint Source: https://github.com/xnicolas99/yachtplus/blob/master/README.md Endpoint to generate a TOTP secret for Two-Factor Authentication setup. Accepts setup_pending tokens. ```http POST /api/auth/2fa/generate ``` -------------------------------- ### Build for Production Source: https://github.com/xnicolas99/yachtplus/blob/master/frontend/README.md Execute this command to compile and minify the project for production deployment. ```bash npm run build ``` -------------------------------- ### Building Frontend for Production Source: https://github.com/xnicolas99/yachtplus/blob/master/AGENTS.md Builds the frontend application for production using npm. The output is written to the 'frontend/dist' directory. ```bash npm run build # writes to frontend/dist ``` -------------------------------- ### Initial User Registration Source: https://github.com/xnicolas99/yachtplus/blob/master/README.md Creates the first administrator user. This endpoint issues a short-lived JWT with a `setup_pending=True` claim in an HttpOnly cookie. The response only includes login and username, not the token. ```APIDOC ## POST /api/setup/register ### Description Creates the first admin user with `is_active=False`, issues a short-lived JWT (15 min) with the `setup_pending=True` claim inside an HttpOnly cookie. Body returns only `{login, username}`, never the token. ### Method POST ### Endpoint /api/setup/register ### Request Body - **login** (string) - Required - The login username for the new admin user. - **username** (string) - Required - The display name for the new admin user. - **password** (string) - Required - The password for the new admin user. ``` -------------------------------- ### Frontend Tests with Vitest Source: https://github.com/xnicolas99/yachtplus/blob/master/README.md Command to run frontend tests using Vitest. ```bash cd frontend npx vitest run ``` -------------------------------- ### Enable 2FA Source: https://github.com/xnicolas99/yachtplus/blob/master/README.md Enables Two-Factor Authentication by verifying a 6-digit code provided by the user after scanning the QR code. Accepts `setup_pending=True` tokens. ```APIDOC ## POST /api/auth/2fa/enable ### Description Enables Two-Factor Authentication by confirming a 6-digit code. Accepts `setup_pending=True` tokens. ### Method POST ### Endpoint /api/auth/2fa/enable ### Request Body - **token** (string) - Required - The 6-digit TOTP code provided by the user. ``` -------------------------------- ### Enable Apache Modules Source: https://github.com/xnicolas99/yachtplus/blob/master/docs/APACHE_REVERSE_PROXY.md Enables essential Apache modules for reverse proxying, WebSocket support, and URL rewriting. Restart Apache after enabling modules. ```bash a2enmod proxy a2enmod proxy_http a2enmod proxy_wstunnel a2enmod rewrite systemctl restart apache2 ``` -------------------------------- ### Setup-Pending Token Security Source: https://github.com/xnicolas99/yachtplus/blob/master/README.md Details on the security measures for setup-pending tokens, including their lifetime and blocking mechanism. ```python 15-minute lifetime, blocked by auth_check_setup_pending once setup is complete (prevents stale-token replay). ``` -------------------------------- ### Project Root Files Source: https://github.com/xnicolas99/yachtplus/blob/master/AGENTS.md Key configuration and build files are located at the project root, including the Dockerfile, docker-compose.yml, nginx configuration, and debugging cheatsheet. ```tree Dockerfile docker-compose.yml nginx.conf DEBUGGING_CHEATSHEET.md README.md # End-user facing; keep in sync with reality ``` -------------------------------- ### Frontend Structure Source: https://github.com/xnicolas99/yachtplus/blob/master/AGENTS.md The frontend is a Vue 3 SPA using Vite. Key directories include source files, router configuration, state management (Vuex), plugins, views, and reusable components. ```tree frontend/ src/ main.js # App bootstrap; DOMPurify allowlist; axios interceptor + 401 → refresh App.vue router/index.js # vue-router 4, navigation guards (setup + auth) store/ # Vuex 4 modules: auth, apps, projects, snackbar, templates, networks, … plugins/vueutils.js # $formatDate / $timeAgo / $truncate (dayjs) plugins/vuetify.js views/ # Page-level components, one per route auth/Login.vue # Cookie-based login + 2FA flow auth/Setup.vue # First-run wizard components/ # Reusable UI: applications/, compose/, charts/, auth/, nav/, … utils/ # Pure JS helpers + their vitest specs vite.config.js package.json ``` -------------------------------- ### Configuring TrustedHostMiddleware for Testing Source: https://github.com/xnicolas99/yachtplus/blob/master/AGENTS.md This configuration snippet in 'backend/tests/conftest.py' sets the 'YACHT_ALLOWED_HOSTS' environment variable before the 'Settings' object is evaluated. This is necessary to prevent 'TrustedHostMiddleware' from rejecting requests made by 'TestClient'. ```python YACHT_ALLOWED_HOSTS=...,testserver ``` -------------------------------- ### Lint and Fix Files Source: https://github.com/xnicolas99/yachtplus/blob/master/frontend/README.md Run this command to lint the project files and automatically fix any style issues. ```bash npm run lint ``` -------------------------------- ### Set Local Database URL for Backend Source: https://github.com/xnicolas99/yachtplus/blob/master/README.md Export the DATABASE_URL environment variable to use a local SQLite database file for the backend during development. ```bash export DATABASE_URL="sqlite:///./local.db" ``` -------------------------------- ### Docker Compose Configuration for Yachtplus Source: https://github.com/xnicolas99/yachtplus/blob/master/README.md Use this Docker Compose file to deploy Yachtplus. Ensure mandatory mounts for docker.sock and config directory are present. ```yaml version: "3" services: yachtplus: image: ghcr.io/yachtplus/yachtplus:devel container_name: yachtplus restart: unless-stopped ports: - "8000:8080" volumes: - /var/run/docker.sock:/var/run/docker.sock - ./config:/config environment: # Pin a SECRET_KEY in production; otherwise the value is generated # once and persisted to /config/.secret_key. # SECRET_KEY: change-me-to-a-long-random-string ENVIRONMENT: production YACHT_ALLOWED_HOSTS: yacht.example.com,localhost YACHT_CORS_ORIGINS: https://yacht.example.com ``` -------------------------------- ### Using aiodocker Client in Async Operations Source: https://github.com/xnicolas99/yachtplus/blob/master/AGENTS.md When performing multiple Docker operations concurrently, create a single 'aiodocker.Docker' client within an 'async with' block and pass it to helper functions. Avoid instantiating a new client for each container operation. ```python async with aiodocker.Docker(...) as client: pass ``` -------------------------------- ### Check Docker Container Logs Source: https://github.com/xnicolas99/yachtplus/blob/master/DEBUGGING_CHEATSHEET.md Monitor container logs in real-time to identify startup errors or specific messages related to Docker socket availability and scheduler locks. ```text docker logs -f yachtplus ``` ```text INFO:api.main:Docker Socket/Proxy is available. ``` ```text CRITICAL: Failed to connect to Docker after 5 attempts ``` ```text INFO:api.main:Scheduler Lock acquired. Starting Scheduler... ``` ```text Scheduler Lock already held... ``` ```text [error] ... open() "/app/static/..." failed (2: No such file or directory) ``` -------------------------------- ### Backend Tests with Pytest Source: https://github.com/xnicolas99/yachtplus/blob/master/README.md Command to run backend tests using pytest. Ensure the DATABASE_URL is set to a test database. ```bash cd backend DATABASE_URL="sqlite:///./test.db" python -m pytest tests/ ``` -------------------------------- ### Request Lifecycle Diagram Source: https://github.com/xnicolas99/yachtplus/blob/master/AGENTS.md Visual representation of how browser requests are handled, routed through nginx to either the FastAPI application or static files, detailing middleware and authorization steps. ```text Browser ── HTTPS ──► nginx (port 8080) │ ├─► /api/* ─► gunicorn ─► FastAPI app (api.main:app) │ │ │ Middleware chain (top→down): │ 1. check_setup_status → 428 if setup not finalized │ 2. CORSMiddleware → uses settings.CORS_ORIGINS │ 3. TrustedHostMiddleware → uses settings.ALLOWED_HOSTS │ 4. add_security_headers → CSP, etc. │ │ │ ▼ │ Router → Endpoint │ - Authorize: get_auth_wrapper = Depends(get_auth_wrapper) │ - auth_check(Authorize) # data routes │ OR auth_check_setup_pending(Authorize, db) # setup/2FA │ - check_permission("perm_x", Authorize, db) # for fine-grained │ - business call → actions/* or db/crud/* │ └─► / ─► static SPA (frontend/dist via nginx) ``` -------------------------------- ### YachtPlus Architecture Overview Source: https://github.com/xnicolas99/yachtplus/blob/master/README.md Diagram illustrating the flow of traffic and communication between the browser, nginx, gunicorn (FastAPI), and Docker services within the YachtPlus container. ```text Browser ──► nginx (port 8080) ──► /api/* ──► gunicorn (FastAPI, /api) └──► / ──► static SPA from frontend/dist FastAPI ──► aiodocker ──► /var/run/docker.sock ──► SQLAlchemy ──► /config/yacht.db (default) ──► APScheduler (background jobs: watchtower polling, audit cleanup) ``` -------------------------------- ### Running Sync I/O in Async Routes Source: https://github.com/xnicolas99/yachtplus/blob/master/AGENTS.md To execute synchronous code within an asynchronous route handler, use a helper function prefixed with '_xxx_sync' and call it via 'await run_in_thread(_xxx_sync, ...)'. This pattern prevents blocking the event loop. ```python await run_in_thread(_xxx_sync, ...) ``` -------------------------------- ### Content Security Policy (CSP) Configuration Source: https://github.com/xnicolas99/yachtplus/blob/master/README.md CSP headers configured to enhance security by restricting the sources from which content can be loaded. ```python script-src 'self' 'unsafe-inline'; object-src 'none'; base-uri 'self'; ``` -------------------------------- ### Trusted Host Middleware Configuration Source: https://github.com/xnicolas99/yachtplus/blob/master/AGENTS.md Implements Trusted Host Middleware to validate the `Host` header against a list of allowed hosts defined in `settings.ALLOWED_HOSTS`. This can be overridden using the `YACHT_ALLOWED_HOSTS` environment variable. ```python # api/main.py: TrustedHostMiddleware # from starlette.middleware.trustedhost import TrustedHostMiddleware # app.add_middleware( # TrustedHostMiddleware, # allowed_hosts=settings.ALLOWED_HOSTS, # except_path=["/api/*"], # Example: exclude API routes if needed # ) ``` -------------------------------- ### Backend API Structure Source: https://github.com/xnicolas99/yachtplus/blob/master/AGENTS.md The backend is organized into distinct directories for API logic, settings, authentication, routers, actions, database operations, and services. This structure promotes modularity and separation of concerns. ```tree backend/ api/ main.py # FastAPI app, middleware stack, router includes settings.py # Pydantic settings + SECRET_KEY bootstrap (fail-fast) auth/ jwt.py # create_access_token, AuthWrapper, cookie helpers auth.py # auth_check / auth_check_setup_pending / check_permission routers/ # One file per feature → FastAPI APIRouter apps.py compose.py containers.py dashboard.py templates.py users.py auth_2fa.py registries.py resources.py smtp.py search.py watchtower.py audit.py app_settings.py setup/setup.py actions/ # Business logic, mostly async wrappers around aiodocker / subprocess db/ models/ # SQLAlchemy ORM models schemas/ # Pydantic request/response shapes crud/ # Pure DB ops (no FastAPI in here) services/ # Background jobs (watchtower poll, audit cleanup) utils/ # Pure helpers: compose parsing, crypto, audit, sanitiser alembic/ # Migrations tests/ # pytest, with conftest.py for env setup requirements.txt ``` -------------------------------- ### Pull Latest Image and Restart Source: https://github.com/xnicolas99/yachtplus/blob/master/DEBUGGING_CHEATSHEET.md Use this command to update to the latest Docker image and restart the services if an old version is detected. ```bash docker-compose pull && docker-compose up -d ``` -------------------------------- ### Check Local Docker Image SHA Source: https://github.com/xnicolas99/yachtplus/blob/master/DEBUGGING_CHEATSHEET.md Compare the SHA digest of the running Docker image with the one on DockerHub/GHCR. If they don't match, pull the latest image and restart. ```bash docker inspect --format='{{.RepoDigests}}' yachtplus ``` -------------------------------- ### Trusted Host Middleware Configuration Source: https://github.com/xnicolas99/yachtplus/blob/master/README.md Configuration for TrustedHostMiddleware to enforce allowed hosts, preventing HTTP Host header attacks. ```python Enforces ALLOWED_HOSTS. Default: localhost,127.0.0.1,[::1]. Override with YACHT_ALLOWED_HOSTS=… ``` -------------------------------- ### Apache VirtualHost Configuration for Yacht Source: https://github.com/xnicolas99/yachtplus/blob/master/docs/APACHE_REVERSE_PROXY.md Configures an Apache VirtualHost to proxy requests to a Yacht instance, including critical settings for WebSocket and Server-Sent Events. ```apache ServerName yacht.example.com ProxyPreserveHost On ProxyRequests Off # Allow encoded slashes AllowEncodedSlashes NoDecode # WebSocket Support (Critical for Terminal) # Redirect Upgrade requests to the websocket backend RewriteEngine On RewriteCond %{HTTP:Upgrade} =websocket [NC] RewriteRule /(.*) ws://localhost:8000/$1 [P,L] # SSE Support (Critical for Stats/Logs) # Disable buffering to allow real-time events SetEnv proxy-nokeepalive 1 SetEnv proxy-sendchunked 1 # General Proxy Pass ProxyPass / http://localhost:8000/ ProxyPassReverse / http://localhost:8000/ # Optional: Increase timeout for long docker operations ProxyTimeout 300 ``` -------------------------------- ### Secret Key Management Source: https://github.com/xnicolas99/yachtplus/blob/master/README.md Configuration for managing the application's secret key, prioritizing environment variables or a persistent file. ```python Reads SECRET_KEY env first, otherwise persists to $SECRET_KEY_FILE (default /config/.secret_key). Refuses to start if it can't be loaded or written — no ephemeral per-process fallback. ``` -------------------------------- ### Enable 2FA TOTP API Endpoint Source: https://github.com/xnicolas99/yachtplus/blob/master/README.md Endpoint to enable Two-Factor Authentication by confirming a TOTP code. Accepts setup_pending tokens. ```http POST /api/auth/2fa/enable ``` -------------------------------- ### Secret Key Management Source: https://github.com/xnicolas99/yachtplus/blob/master/AGENTS.md Ensures the `SECRET_KEY` is read from the environment or persisted to `SECRET_KEY_FILE`. The application fails fast if neither is possible, preventing the use of an ephemeral fallback key. ```python # api/settings.py: get_or_create_secret_key # import os # from pathlib import Path # SECRET_KEY_FILE = Path("SECRET_KEY") # def get_or_create_secret_key() -> str: # secret_key = os.environ.get("SECRET_KEY") # if secret_key: # return secret_key # if SECRET_KEY_FILE.exists(): # return SECRET_KEY_FILE.read_text().strip() # # Fail fast if no key is found and cannot be created # raise RuntimeError("SECRET_KEY not found in environment or file.") # SECRET_KEY = get_or_create_secret_key() ``` -------------------------------- ### Brute-Force Protection Configuration Source: https://github.com/xnicolas99/yachtplus/blob/master/README.md Rate limiting and IP restriction for login endpoints to protect against brute-force attacks. ```python slowapi rate limit 5/minute on /login and /login_cookie, plus IP-restriction + LoginAttempt table for fail2ban-style blocking. ``` -------------------------------- ### Rate Limiting Login Attempts Source: https://github.com/xnicolas99/yachtplus/blob/master/AGENTS.md Applies a rate limit of 5 requests per minute to the login endpoint to mitigate brute-force attacks. It also tracks per-IP login attempts in the database for fail2ban-style blocking. ```python # backend/api/routers/users.py # from slowapi import Limiter # from slowapi.util import get_remote_address # limiter = Limiter(key_func=get_remote_address) # @router.post("/login") # @limiter.limit("5/minute") # async def login(...): # # ... login logic ... # pass ``` -------------------------------- ### CORS Configuration Source: https://github.com/xnicolas99/yachtplus/blob/master/README.md CORS settings for handling cross-origin requests, defaulting to localhost variants. ```python Defaults to localhost variants; override with YACHT_CORS_ORIGINS=… ``` -------------------------------- ### Content Security Policy (CSP) Configuration Source: https://github.com/xnicolas99/yachtplus/blob/master/AGENTS.md Defines the Content Security Policy for the application, specifically allowing inline scripts (`'unsafe-inline'`) but disallowing `unsafe-eval`. This is configured within the `add_security_headers` middleware. ```python # api/main.py: add_security_headers # from starlette.middleware.base import BaseHTTPMiddleware # from starlette.requests import Request # from starlette.responses import Response # class SecurityHeadersMiddleware(BaseHTTPMiddleware): # async def dispatch(self, request: Request, call_next): # response = await call_next(request) # response.headers["Content-Security-Policy"] = \ # "script-src 'self' 'unsafe-inline'; object-src 'none'; base-uri 'none';" # return response ``` -------------------------------- ### CORS Middleware Configuration Source: https://github.com/xnicolas99/yachtplus/blob/master/AGENTS.md Configures Cross-Origin Resource Sharing (CORS) middleware based on `settings.CORS_ORIGINS`. The allowed origins can be overridden using the `YACHT_CORS_ORIGINS` environment variable. ```python # api/main.py: CORSMiddleware # from starlette.middleware.cors import CORSMiddleware # app.add_middleware( # CORSMiddleware, # allow_origins=settings.CORS_ORIGINS, # allow_credentials=True, # allow_methods=["*"], # allow_headers=["*"], # ) ``` -------------------------------- ### User Login (Cookie) Source: https://github.com/xnicolas99/yachtplus/blob/master/README.md Handles user login using credentials and a TOTP code. Upon successful authentication, it sets an HttpOnly cookie containing the JWT. ```APIDOC ## POST /api/auth/login_cookie ### Description Validates user credentials and TOTP code, then sets the HttpOnly authentication cookie. ### Method POST ### Endpoint /api/auth/login_cookie ### Request Body - **username** (string) - Required - The user's username. - **password** (string) - Required - The user's password. - **totp_code** (string) - Required - The 6-digit TOTP code. ``` -------------------------------- ### HTML Sanitization Configuration Source: https://github.com/xnicolas99/yachtplus/blob/master/README.md Configuration for HTML sanitization using DOMPurify, with an explicit allowlist for safe tags and attributes. ```javascript $sanitize uses DOMPurify with an explicit allowlist (b,i,em,strong,a,p,br,ul,ol,li,code,pre, only http(s)/mailto: URLs). ``` -------------------------------- ### Clean Rebuild: Remove Image Source: https://github.com/xnicolas99/yachtplus/blob/master/DEBUGGING_CHEATSHEET.md Remove the local Docker image to ensure a fresh pull on the next startup. This is part of the 'nuclear option' for debugging. ```bash docker rmi ghcr.io/yachtplus/yachtplus:latest ``` -------------------------------- ### Clean Rebuild: Stop Containers Source: https://github.com/xnicolas99/yachtplus/blob/master/DEBUGGING_CHEATSHEET.md Stop all running Docker containers managed by docker-compose before proceeding with a clean rebuild. ```bash docker-compose down ``` -------------------------------- ### Login with Cookie API Endpoint Source: https://github.com/xnicolas99/yachtplus/blob/master/README.md Endpoint for subsequent user logins using HttpOnly cookies, requiring a TOTP code. ```http POST /api/auth/login_cookie ``` -------------------------------- ### Template SSRF Mitigation Pattern Source: https://github.com/xnicolas99/yachtplus/blob/master/AGENTS.md Provides a pattern (`SafeRedirectHandler`) for safely handling user-supplied URLs to prevent Server-Side Request Forgery (SSRF) vulnerabilities. This pattern should be reused for any external URL fetching initiated by user input. ```python # api/db/crud/templates.py: SafeRedirectHandler # import httpx # from urllib.parse import urlparse # class SafeRedirectHandler: # def __init__(self, base_url: str): # self.base_url = urlparse(base_url) # async def fetch(self, url: str): # parsed_url = urlparse(url) # # Ensure the URL is relative and within the allowed base domain # if parsed_url.netloc or parsed_url.scheme: # raise ValueError("URL must be relative and on the same domain.") # full_url = self.base_url.scheme + "://" + self.base_url.netloc + url # # Use httpx for making the request, with appropriate security checks # async with httpx.AsyncClient() as client: # response = await client.get(full_url) # response.raise_for_status() # Raise an exception for bad status codes # return response.text # # Example Usage: # # handler = SafeRedirectHandler("http://example.com/base/") # # html_content = await handler.fetch("/path/to/resource") ``` -------------------------------- ### HttpOnly Cookie Security Configuration Source: https://github.com/xnicolas99/yachtplus/blob/master/README.md Configuration details for HttpOnly cookies used for JWT authentication, including secure and samesite attributes. ```python secure=True whenever ENVIRONMENT=production; samesite=lax ``` -------------------------------- ### HTML Sanitization with DOMPurify Source: https://github.com/xnicolas99/yachtplus/blob/master/AGENTS.md Utilizes DOMPurify for HTML sanitization in the frontend's `main.js` to prevent XSS attacks when rendering content via `v-html`. It uses an explicit allowlist for security. ```javascript // frontend/src/main.js // import DOMPurify from 'dompurify'; // const sanitize = (html) => { // return DOMPurify.sanitize(html, { // USE_PROFILES: { html: true }, // // Add specific allowlist configurations if needed // }); // }; // // Example usage: // // Vue.prototype.$sanitize = sanitize; ``` -------------------------------- ### WebSocket Authentication Source: https://github.com/xnicolas99/yachtplus/blob/master/AGENTS.md Handles authentication for WebSocket connections by reading the cookie directly from the handshake. It explicitly avoids accepting tokens via URL or query parameters for security. ```python # backend/api/routers/containers.py # from fastapi import WebSocket, Depends # from fastapi.security import OAuth2PasswordBearer # # Example assuming a dependency that extracts token from cookie # async def get_token_from_cookie(request: Request): # token = request.cookies.get("access_token_cookie") # if not token: # raise HTTPException(status_code=401, detail="Not authenticated") # return token # @app.websocket("/ws/containers") # async def websocket_endpoint(websocket: WebSocket, token: str = Depends(get_token_from_cookie)): # # ... websocket logic using the authenticated token ... # pass ``` -------------------------------- ### Clean Rebuild: Prune Volumes Source: https://github.com/xnicolas99/yachtplus/blob/master/DEBUGGING_CHEATSHEET.md Remove Docker volumes to clear potentially corrupt data or configuration. WARNING: This action deletes data and should be used with caution after verifying volume names. ```bash docker volume rm yacht_config ``` -------------------------------- ### Setting HttpOnly Auth Cookie Source: https://github.com/xnicolas99/yachtplus/blob/master/AGENTS.md Configures the JWT access token to be stored in an HttpOnly cookie, preventing JavaScript access. The `secure` flag is set to `True` in production environments. ```python # api/auth/jwt.py: set_access_cookies # from starlette.responses import Response # def set_access_cookies(response: Response, access_token: str): # response.set_cookie( # "access_token_cookie", # access_token, # httponly=True, # secure=settings.ENVIRONMENT == "production", # samesite="lax", # ) # return response ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.