Add settings page with change password, fix terminal ws bug
Deploy Dashboard / deploy (push) Failing after 2m5s
Deploy Dashboard / deploy (push) Failing after 2m5s
This commit is contained in:
+22
-10
@@ -60,27 +60,39 @@ async def get_current_user_ws(token: str):
|
||||
raise credentials_exception
|
||||
return username
|
||||
|
||||
# TOTP Persistenceturn username
|
||||
|
||||
# TOTP Persistence
|
||||
AUTH_FILE = config.VOLUME_ROOT + "/docker/nas-dashboard/auth.json"
|
||||
import json, os
|
||||
|
||||
def load_totp_secret():
|
||||
def _load_auth_data():
|
||||
try:
|
||||
import json
|
||||
if os.path.exists(AUTH_FILE):
|
||||
with open(AUTH_FILE, "r") as f:
|
||||
data = json.load(f)
|
||||
return data.get("totp_secret", "")
|
||||
return json.load(f)
|
||||
except Exception:
|
||||
pass
|
||||
return config.TOTP_SECRET
|
||||
return {}
|
||||
|
||||
def save_totp_secret(secret: str):
|
||||
import json
|
||||
def _save_auth_data(data):
|
||||
os.makedirs(os.path.dirname(AUTH_FILE), exist_ok=True)
|
||||
with open(AUTH_FILE, "w") as f:
|
||||
json.dump({"totp_secret": secret}, f)
|
||||
json.dump(data, f)
|
||||
|
||||
def load_totp_secret():
|
||||
return _load_auth_data().get("totp_secret", "") or config.TOTP_SECRET
|
||||
|
||||
def save_totp_secret(secret: str):
|
||||
data = _load_auth_data()
|
||||
data["totp_secret"] = secret
|
||||
_save_auth_data(data)
|
||||
|
||||
def load_password_hash():
|
||||
return _load_auth_data().get("password_hash", "") or config.ADMIN_PASSWORD_HASH
|
||||
|
||||
def save_password_hash(hashed: str):
|
||||
data = _load_auth_data()
|
||||
data["password_hash"] = hashed
|
||||
_save_auth_data(data)
|
||||
|
||||
def verify_totp(token: str, secret: str = None):
|
||||
if secret is None:
|
||||
|
||||
@@ -28,7 +28,7 @@ class Verify2FARequest(BaseModel):
|
||||
@router.post("/login", response_model=Token)
|
||||
async def login(creds: LoginRequest):
|
||||
# Verify username/password
|
||||
if creds.username != config.ADMIN_USER or not auth.verify_password(creds.password, config.ADMIN_PASSWORD_HASH):
|
||||
if creds.username != config.ADMIN_USER or not auth.verify_password(creds.password, auth.load_password_hash()):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Incorrect username or password",
|
||||
@@ -84,3 +84,16 @@ async def verify_2fa_setup(request: Verify2FARequest, current_user: str = Depend
|
||||
async def disable_2fa(current_user: str = Depends(auth.get_current_user)):
|
||||
auth.save_totp_secret("")
|
||||
return {"message": "2FA disabled"}
|
||||
|
||||
class ChangePasswordRequest(BaseModel):
|
||||
current_password: str
|
||||
new_password: str
|
||||
|
||||
@router.post("/change-password")
|
||||
async def change_password(req: ChangePasswordRequest, current_user: str = Depends(auth.get_current_user)):
|
||||
if not auth.verify_password(req.current_password, auth.load_password_hash()):
|
||||
raise HTTPException(status_code=400, detail="Current password is incorrect")
|
||||
if len(req.new_password) < 8:
|
||||
raise HTTPException(status_code=400, detail="Password must be at least 8 characters")
|
||||
auth.save_password_hash(auth.get_password_hash(req.new_password))
|
||||
return {"message": "Password changed successfully"}
|
||||
|
||||
@@ -16,7 +16,7 @@ async def ws_endpoint(websocket: WebSocket, user: str = Depends(auth.get_current
|
||||
return
|
||||
|
||||
|
||||
await ws.accept()
|
||||
await websocket.accept()
|
||||
master_fd, slave_fd = pty.openpty()
|
||||
pid = os.fork()
|
||||
|
||||
@@ -40,7 +40,7 @@ async def ws_endpoint(websocket: WebSocket, user: str = Depends(auth.get_current
|
||||
data = os.read(master_fd, 4096)
|
||||
if not data:
|
||||
break
|
||||
await ws.send_bytes(data)
|
||||
await websocket.send_bytes(data)
|
||||
except (OSError, WebSocketDisconnect):
|
||||
pass
|
||||
|
||||
@@ -53,7 +53,7 @@ async def ws_endpoint(websocket: WebSocket, user: str = Depends(auth.get_current
|
||||
|
||||
try:
|
||||
while True:
|
||||
msg = await ws.receive()
|
||||
msg = await websocket.receive()
|
||||
if "bytes" in msg and msg["bytes"]:
|
||||
data = msg["bytes"]
|
||||
# Handle resize: first byte 0x01 means resize message
|
||||
|
||||
Reference in New Issue
Block a user