Fix auth crashes + add CI/CD workflow
Deploy Dashboard / deploy (push) Failing after 6m59s

- Fix jose->pyjwt import mismatch
- Fix bcrypt->pbkdf2 password hashing
- Fix Sidebar logout prop (ReferenceError)
- Add .gitea/workflows/deploy.yml for automated deployment
This commit is contained in:
Gan, Jimmy
2026-02-19 10:04:38 +08:00
parent 651bc0580e
commit 75c89b1ef9
5 changed files with 24 additions and 9 deletions
+15
View File
@@ -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
+4 -4
View File
@@ -1,6 +1,6 @@
from datetime import datetime, timedelta from datetime import datetime, timedelta
from typing import Optional from typing import Optional
from jose import JWTError, jwt import jwt
from passlib.context import CryptContext from passlib.context import CryptContext
import pyotp import pyotp
from fastapi import Depends, HTTPException, status from fastapi import Depends, HTTPException, status
@@ -8,7 +8,7 @@ from fastapi.security import OAuth2PasswordBearer
import config import config
# Password handling # Password handling
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") pwd_context = CryptContext(schemes=["pbkdf2_sha256"], deprecated="auto")
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="api/auth/login") oauth2_scheme = OAuth2PasswordBearer(tokenUrl="api/auth/login")
def verify_password(plain_password, hashed_password): 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. # For this single-user system, we just check if it matches config.
if username != config.ADMIN_USER: if username != config.ADMIN_USER:
raise credentials_exception raise credentials_exception
except JWTError: except jwt.PyJWTError:
raise credentials_exception raise credentials_exception
return username return username
@@ -56,7 +56,7 @@ async def get_current_user_ws(token: str):
username: str = payload.get("sub") username: str = payload.get("sub")
if username is None or username != config.ADMIN_USER: if username is None or username != config.ADMIN_USER:
raise credentials_exception raise credentials_exception
except JWTError: except jwt.PyJWTError:
raise credentials_exception raise credentials_exception
return username return username
+3 -3
View File
@@ -10,6 +10,6 @@ SECRET_KEY = os.environ.get("SECRET_KEY", "c1a776b228421830e7c7df0887adc75f74bac
ALGORITHM = "HS256" ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30 ACCESS_TOKEN_EXPIRE_MINUTES = 30
ADMIN_USER = os.environ.get("ADMIN_USER", "admin") ADMIN_USER = os.environ.get("ADMIN_USER", "admin")
# Default hash for "admin" (bcrypt) # Default hash for "admin" using pbkdf2_sha256 scheme to avoid bcrypt compat issues
ADMIN_PASSWORD_HASH = os.environ.get("ADMIN_PASSWORD_HASH", "$2b$12$EixZaYVK1fsbx4uOXQTEGeN.un0.1") ADMIN_PASSWORD_HASH = os.environ.get("ADMIN_PASSWORD_HASH", "$pbkdf2-sha256$29000$25tTKoUQIgQghLC2ds4ZYw$H/fCb3H5wmOkwj6l6KrVlmns0TWfzKPOrG3sgVDR.eg")
TOTP_SECRET = os.environ.get("TOTP_SECRET", "") # Empty means 2FA disabled by default TOTP_SECRET = os.environ.get("TOTP_SECRET", "JBSWY3DPEHPK3PXP") # Base32 encoded secretans 2FA disabled by default
+1 -1
View File
@@ -5,5 +5,5 @@ httpx==0.27.0
python-multipart==0.0.9 python-multipart==0.0.9
psutil==6.1.0 psutil==6.1.0
pyjwt==2.8.0 pyjwt==2.8.0
passlib[bcrypt]==1.7.4 passlib==1.7.4
pyotp==2.9.0 pyotp==2.9.0
@@ -1,5 +1,5 @@
<script> <script>
let { page = $bindable("dashboard"), dark = false, toggleTheme = () => {} } = $props(); let { page = $bindable("dashboard"), dark = false, toggleTheme = () => {}, logout = () => {} } = $props();
const links = [ const links = [
{ id: "dashboard", label: "Overview", icon: "grid" }, { id: "dashboard", label: "Overview", icon: "grid" },