diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml new file mode 100644 index 0000000..de6c782 --- /dev/null +++ b/.gitea/workflows/deploy.yml @@ -0,0 +1,15 @@ +name: Deploy Dashboard +on: + push: + branches: [main] + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Deploy Dashboard + run: | + docker compose -f dashboard/docker-compose.yml up -d --build dashboard diff --git a/dashboard/backend/auth.py b/dashboard/backend/auth.py index 8bbcc06..6dc6b40 100644 --- a/dashboard/backend/auth.py +++ b/dashboard/backend/auth.py @@ -1,6 +1,6 @@ from datetime import datetime, timedelta from typing import Optional -from jose import JWTError, jwt +import jwt from passlib.context import CryptContext import pyotp from fastapi import Depends, HTTPException, status @@ -8,7 +8,7 @@ from fastapi.security import OAuth2PasswordBearer import config # Password handling -pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") +pwd_context = CryptContext(schemes=["pbkdf2_sha256"], deprecated="auto") oauth2_scheme = OAuth2PasswordBearer(tokenUrl="api/auth/login") def verify_password(plain_password, hashed_password): @@ -42,7 +42,7 @@ async def get_current_user(token: str = Depends(oauth2_scheme)): # For this single-user system, we just check if it matches config. if username != config.ADMIN_USER: raise credentials_exception - except JWTError: + except jwt.PyJWTError: raise credentials_exception return username @@ -56,7 +56,7 @@ async def get_current_user_ws(token: str): username: str = payload.get("sub") if username is None or username != config.ADMIN_USER: raise credentials_exception - except JWTError: + except jwt.PyJWTError: raise credentials_exception return username diff --git a/dashboard/backend/config.py b/dashboard/backend/config.py index 998b61d..e6e223a 100644 --- a/dashboard/backend/config.py +++ b/dashboard/backend/config.py @@ -10,6 +10,6 @@ SECRET_KEY = os.environ.get("SECRET_KEY", "c1a776b228421830e7c7df0887adc75f74bac ALGORITHM = "HS256" ACCESS_TOKEN_EXPIRE_MINUTES = 30 ADMIN_USER = os.environ.get("ADMIN_USER", "admin") -# Default hash for "admin" (bcrypt) -ADMIN_PASSWORD_HASH = os.environ.get("ADMIN_PASSWORD_HASH", "$2b$12$EixZaYVK1fsbx4uOXQTEGeN.un0.1") -TOTP_SECRET = os.environ.get("TOTP_SECRET", "") # Empty means 2FA disabled by default +# Default hash for "admin" using pbkdf2_sha256 scheme to avoid bcrypt compat issues +ADMIN_PASSWORD_HASH = os.environ.get("ADMIN_PASSWORD_HASH", "$pbkdf2-sha256$29000$25tTKoUQIgQghLC2ds4ZYw$H/fCb3H5wmOkwj6l6KrVlmns0TWfzKPOrG3sgVDR.eg") +TOTP_SECRET = os.environ.get("TOTP_SECRET", "JBSWY3DPEHPK3PXP") # Base32 encoded secretans 2FA disabled by default diff --git a/dashboard/backend/requirements.txt b/dashboard/backend/requirements.txt index db08d76..acb5ef8 100644 --- a/dashboard/backend/requirements.txt +++ b/dashboard/backend/requirements.txt @@ -5,5 +5,5 @@ httpx==0.27.0 python-multipart==0.0.9 psutil==6.1.0 pyjwt==2.8.0 -passlib[bcrypt]==1.7.4 +passlib==1.7.4 pyotp==2.9.0 diff --git a/dashboard/frontend/src/components/Sidebar.svelte b/dashboard/frontend/src/components/Sidebar.svelte index cdbfecd..beda60c 100644 --- a/dashboard/frontend/src/components/Sidebar.svelte +++ b/dashboard/frontend/src/components/Sidebar.svelte @@ -1,5 +1,5 @@