Refactor to not use status: success, but HTTP codes, and renamed the error key to detail to match FastAPI's own.
This commit is contained in:
parent
cf138d90c5
commit
9f423135ed
@ -48,7 +48,7 @@ onMounted(async () => {
|
|||||||
try {
|
try {
|
||||||
const response = await fetch('/auth/create-link', { method: 'POST' })
|
const response = await fetch('/auth/create-link', { method: 'POST' })
|
||||||
const result = await response.json()
|
const result = await response.json()
|
||||||
if (result.error) throw new Error(result.error)
|
if (result.detail) throw new Error(result.detail)
|
||||||
|
|
||||||
url.value = result.url
|
url.value = result.url
|
||||||
|
|
||||||
|
@ -36,8 +36,8 @@ export const useAuthStore = defineStore('auth', {
|
|||||||
headers: {'Authorization': `Bearer ${sessionToken}`},
|
headers: {'Authorization': `Bearer ${sessionToken}`},
|
||||||
})
|
})
|
||||||
const result = await response.json()
|
const result = await response.json()
|
||||||
if (result.error) {
|
if (result.detail) {
|
||||||
throw new Error(result.error)
|
throw new Error(result.detail)
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
},
|
},
|
||||||
@ -73,7 +73,7 @@ export const useAuthStore = defineStore('auth', {
|
|||||||
async loadUserInfo() {
|
async loadUserInfo() {
|
||||||
const response = await fetch('/auth/user-info', {method: 'POST'})
|
const response = await fetch('/auth/user-info', {method: 'POST'})
|
||||||
const result = await response.json()
|
const result = await response.json()
|
||||||
if (result.error) throw new Error(`Server: ${result.error}`)
|
if (result.detail) throw new Error(`Server: ${result.detail}`)
|
||||||
|
|
||||||
this.currentUser = result.user
|
this.currentUser = result.user
|
||||||
this.currentCredentials = result.credentials || []
|
this.currentCredentials = result.credentials || []
|
||||||
@ -82,9 +82,9 @@ export const useAuthStore = defineStore('auth', {
|
|||||||
console.log('User info loaded:', result)
|
console.log('User info loaded:', result)
|
||||||
},
|
},
|
||||||
async deleteCredential(uuid) {
|
async deleteCredential(uuid) {
|
||||||
const response = await fetch(`/auth/credential/${uuid}`, {method: 'DELETE'})
|
const response = await fetch(`/auth/credential/${uuid}`, {method: 'Delete'})
|
||||||
const result = await response.json()
|
const result = await response.json()
|
||||||
if (result.error) throw new Error(`Server: ${result.error}`)
|
if (result.detail) throw new Error(`Server: ${result.detail}`)
|
||||||
|
|
||||||
await this.loadUserInfo()
|
await this.loadUserInfo()
|
||||||
},
|
},
|
||||||
|
@ -57,8 +57,8 @@ class AwaitableWebSocket extends WebSocket {
|
|||||||
console.error("Failed to parse JSON from WebSocket message", data, err)
|
console.error("Failed to parse JSON from WebSocket message", data, err)
|
||||||
throw new Error("Failed to parse JSON from WebSocket message")
|
throw new Error("Failed to parse JSON from WebSocket message")
|
||||||
}
|
}
|
||||||
if (parsed.error) {
|
if (parsed.detail) {
|
||||||
throw new Error(`Server: ${parsed.error}`)
|
throw new Error(`Server: ${parsed.detail}`)
|
||||||
}
|
}
|
||||||
return parsed
|
return parsed
|
||||||
}
|
}
|
||||||
|
@ -28,17 +28,17 @@ def register_api_routes(app: FastAPI):
|
|||||||
"""Register all API routes on the FastAPI app."""
|
"""Register all API routes on the FastAPI app."""
|
||||||
|
|
||||||
@app.post("/auth/validate")
|
@app.post("/auth/validate")
|
||||||
async def validate_token(auth=Cookie(None)):
|
async def validate_token(response: Response, auth=Cookie(None)):
|
||||||
"""Lightweight token validation endpoint."""
|
"""Lightweight token validation endpoint."""
|
||||||
try:
|
try:
|
||||||
s = await get_session(auth)
|
s = await get_session(auth)
|
||||||
return {
|
return {
|
||||||
"status": "success",
|
|
||||||
"valid": True,
|
"valid": True,
|
||||||
"user_uuid": str(s.user_uuid),
|
"user_uuid": str(s.user_uuid),
|
||||||
}
|
}
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return {"status": "error", "valid": False}
|
response.status_code = 401
|
||||||
|
return {"valid": False}
|
||||||
|
|
||||||
@app.post("/auth/user-info")
|
@app.post("/auth/user-info")
|
||||||
async def api_user_info(response: Response, auth=Cookie(None)):
|
async def api_user_info(response: Response, auth=Cookie(None)):
|
||||||
@ -84,7 +84,6 @@ def register_api_routes(app: FastAPI):
|
|||||||
credentials.sort(key=lambda cred: cred["created_at"])
|
credentials.sort(key=lambda cred: cred["created_at"])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"status": "success",
|
|
||||||
"authenticated": not reset,
|
"authenticated": not reset,
|
||||||
"session_type": s.info["type"],
|
"session_type": s.info["type"],
|
||||||
"user": {
|
"user": {
|
||||||
@ -99,24 +98,23 @@ def register_api_routes(app: FastAPI):
|
|||||||
}
|
}
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
response.status_code = 400
|
response.status_code = 400
|
||||||
return {"error": f"Failed to get user info: {e}"}
|
return {"detail": f"Failed to get user info: {e}"}
|
||||||
except Exception:
|
except Exception:
|
||||||
response.status_code = 500
|
response.status_code = 500
|
||||||
|
return {"detail": "Failed to get user info"}
|
||||||
return {"error": "Failed to get user info"}
|
|
||||||
|
|
||||||
@app.post("/auth/logout")
|
@app.post("/auth/logout")
|
||||||
async def api_logout(response: Response, auth=Cookie(None)):
|
async def api_logout(response: Response, auth=Cookie(None)):
|
||||||
"""Log out the current user by clearing the session cookie and deleting from database."""
|
"""Log out the current user by clearing the session cookie and deleting from database."""
|
||||||
if not auth:
|
if not auth:
|
||||||
return {"status": "success", "message": "Already logged out"}
|
return {"message": "Already logged out"}
|
||||||
# Remove from database if possible
|
# Remove from database if possible
|
||||||
try:
|
try:
|
||||||
await db.instance.delete_session(session_key(auth))
|
await db.instance.delete_session(session_key(auth))
|
||||||
except Exception:
|
except Exception:
|
||||||
...
|
...
|
||||||
response.delete_cookie("auth")
|
response.delete_cookie("auth")
|
||||||
return {"status": "success", "message": "Logged out successfully"}
|
return {"message": "Logged out successfully"}
|
||||||
|
|
||||||
@app.post("/auth/set-session")
|
@app.post("/auth/set-session")
|
||||||
async def api_set_session(response: Response, auth=Depends(bearer_auth)):
|
async def api_set_session(response: Response, auth=Depends(bearer_auth)):
|
||||||
@ -128,17 +126,16 @@ def register_api_routes(app: FastAPI):
|
|||||||
session.set_session_cookie(response, auth.credentials)
|
session.set_session_cookie(response, auth.credentials)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"status": "success",
|
|
||||||
"message": "Session cookie set successfully",
|
"message": "Session cookie set successfully",
|
||||||
"user_uuid": str(user.user_uuid),
|
"user_uuid": str(user.user_uuid),
|
||||||
}
|
}
|
||||||
|
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
response.status_code = 400
|
response.status_code = 400
|
||||||
return {"error": str(e)}
|
return {"detail": str(e)}
|
||||||
except Exception:
|
except Exception:
|
||||||
response.status_code = 500
|
response.status_code = 500
|
||||||
return {"error": "Failed to set session"}
|
return {"detail": "Failed to set session"}
|
||||||
|
|
||||||
@app.delete("/auth/credential/{uuid}")
|
@app.delete("/auth/credential/{uuid}")
|
||||||
async def api_delete_credential(
|
async def api_delete_credential(
|
||||||
@ -147,11 +144,11 @@ def register_api_routes(app: FastAPI):
|
|||||||
"""Delete a specific credential for the current user."""
|
"""Delete a specific credential for the current user."""
|
||||||
try:
|
try:
|
||||||
await delete_credential(uuid, auth)
|
await delete_credential(uuid, auth)
|
||||||
return {"status": "success", "message": "Credential deleted successfully"}
|
return {"message": "Credential deleted successfully"}
|
||||||
|
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
response.status_code = 400
|
response.status_code = 400
|
||||||
return {"error": str(e)}
|
return {"detail": str(e)}
|
||||||
except Exception:
|
except Exception:
|
||||||
response.status_code = 500
|
response.status_code = 500
|
||||||
return {"error": "Failed to delete credential"}
|
return {"detail": "Failed to delete credential"}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
from fastapi import Cookie, HTTPException, Request
|
from fastapi import Cookie, HTTPException, Request, Response
|
||||||
from fastapi.responses import RedirectResponse
|
from fastapi.responses import RedirectResponse
|
||||||
|
|
||||||
from ..authsession import expires, get_session
|
from ..authsession import expires, get_session
|
||||||
@ -13,7 +13,7 @@ def register_reset_routes(app):
|
|||||||
"""Register all device addition/reset routes on the FastAPI app."""
|
"""Register all device addition/reset routes on the FastAPI app."""
|
||||||
|
|
||||||
@app.post("/auth/create-link")
|
@app.post("/auth/create-link")
|
||||||
async def api_create_link(request: Request, auth=Cookie(None)):
|
async def api_create_link(request: Request, response: Response, auth=Cookie(None)):
|
||||||
"""Create a device addition link for the authenticated user."""
|
"""Create a device addition link for the authenticated user."""
|
||||||
try:
|
try:
|
||||||
# Require authentication
|
# Require authentication
|
||||||
@ -33,16 +33,17 @@ def register_reset_routes(app):
|
|||||||
url = f"{request.headers['origin']}{path}"
|
url = f"{request.headers['origin']}{path}"
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"status": "success",
|
|
||||||
"message": "Registration link generated successfully",
|
"message": "Registration link generated successfully",
|
||||||
"url": url,
|
"url": url,
|
||||||
"expires": expires().isoformat(),
|
"expires": expires().isoformat(),
|
||||||
}
|
}
|
||||||
|
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return {"error": "Authentication required"}
|
response.status_code = 401
|
||||||
|
return {"detail": "Authentication required"}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return {"error": f"Failed to create registration link: {str(e)}"}
|
response.status_code = 500
|
||||||
|
return {"detail": f"Failed to create registration link: {str(e)}"}
|
||||||
|
|
||||||
@app.get("/auth/{reset_token}")
|
@app.get("/auth/{reset_token}")
|
||||||
async def reset_authentication(
|
async def reset_authentication(
|
||||||
|
@ -16,9 +16,10 @@ import uuid7
|
|||||||
from fastapi import Cookie, FastAPI, Query, WebSocket, WebSocketDisconnect
|
from fastapi import Cookie, FastAPI, Query, WebSocket, WebSocketDisconnect
|
||||||
from webauthn.helpers.exceptions import InvalidAuthenticationResponse
|
from webauthn.helpers.exceptions import InvalidAuthenticationResponse
|
||||||
|
|
||||||
from ..authsession import EXPIRES, create_session, get_session
|
from ..authsession import EXPIRES, create_session, get_reset, get_session
|
||||||
from ..db import User, db
|
from ..db import User, db
|
||||||
from ..sansio import Passkey
|
from ..sansio import Passkey
|
||||||
|
from ..util import passphrase
|
||||||
from ..util.tokens import create_token, session_key
|
from ..util.tokens import create_token, session_key
|
||||||
from .session import infodict
|
from .session import infodict
|
||||||
|
|
||||||
@ -80,18 +81,17 @@ async def websocket_register_new(
|
|||||||
|
|
||||||
await ws.send_json(
|
await ws.send_json(
|
||||||
{
|
{
|
||||||
"status": "success",
|
|
||||||
"user_uuid": str(user_uuid),
|
"user_uuid": str(user_uuid),
|
||||||
"session_token": token,
|
"session_token": token,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
await ws.send_json({"error": str(e)})
|
await ws.send_json({"detail": str(e)})
|
||||||
except WebSocketDisconnect:
|
except WebSocketDisconnect:
|
||||||
pass
|
pass
|
||||||
except Exception:
|
except Exception:
|
||||||
logging.exception("Internal Server Error")
|
logging.exception("Internal Server Error")
|
||||||
await ws.send_json({"error": "Internal Server Error"})
|
await ws.send_json({"detail": "Internal Server Error"})
|
||||||
|
|
||||||
|
|
||||||
@app.websocket("/add_credential")
|
@app.websocket("/add_credential")
|
||||||
@ -100,7 +100,9 @@ async def websocket_register_add(ws: WebSocket, auth=Cookie(None)):
|
|||||||
await ws.accept()
|
await ws.accept()
|
||||||
origin = ws.headers["origin"]
|
origin = ws.headers["origin"]
|
||||||
try:
|
try:
|
||||||
s = await get_session(auth, reset_allowed=True)
|
# Try to get either a regular session or a reset session
|
||||||
|
reset = passphrase.is_well_formed(auth)
|
||||||
|
s = await (get_reset if reset else get_session)(auth)
|
||||||
user_uuid = s.user_uuid
|
user_uuid = s.user_uuid
|
||||||
|
|
||||||
# Get user information to get the user_name
|
# Get user information to get the user_name
|
||||||
@ -126,7 +128,6 @@ async def websocket_register_add(ws: WebSocket, auth=Cookie(None)):
|
|||||||
|
|
||||||
await ws.send_json(
|
await ws.send_json(
|
||||||
{
|
{
|
||||||
"status": "success",
|
|
||||||
"user_uuid": str(user.uuid),
|
"user_uuid": str(user.uuid),
|
||||||
"credential_uuid": str(credential.uuid),
|
"credential_uuid": str(credential.uuid),
|
||||||
"session_token": token,
|
"session_token": token,
|
||||||
@ -134,12 +135,12 @@ async def websocket_register_add(ws: WebSocket, auth=Cookie(None)):
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
await ws.send_json({"error": str(e)})
|
await ws.send_json({"detail": str(e)})
|
||||||
except WebSocketDisconnect:
|
except WebSocketDisconnect:
|
||||||
pass
|
pass
|
||||||
except Exception:
|
except Exception:
|
||||||
logging.exception("Internal Server Error")
|
logging.exception("Internal Server Error")
|
||||||
await ws.send_json({"error": "Internal Server Error"})
|
await ws.send_json({"detail": "Internal Server Error"})
|
||||||
|
|
||||||
|
|
||||||
@app.websocket("/authenticate")
|
@app.websocket("/authenticate")
|
||||||
@ -168,16 +169,15 @@ async def websocket_authenticate(ws: WebSocket):
|
|||||||
|
|
||||||
await ws.send_json(
|
await ws.send_json(
|
||||||
{
|
{
|
||||||
"status": "success",
|
|
||||||
"user_uuid": str(stored_cred.user_uuid),
|
"user_uuid": str(stored_cred.user_uuid),
|
||||||
"session_token": token,
|
"session_token": token,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
except (ValueError, InvalidAuthenticationResponse) as e:
|
except (ValueError, InvalidAuthenticationResponse) as e:
|
||||||
logging.exception("ValueError")
|
logging.exception("ValueError")
|
||||||
await ws.send_json({"error": str(e)})
|
await ws.send_json({"detail": str(e)})
|
||||||
except WebSocketDisconnect:
|
except WebSocketDisconnect:
|
||||||
pass
|
pass
|
||||||
except Exception:
|
except Exception:
|
||||||
logging.exception("Internal Server Error")
|
logging.exception("Internal Server Error")
|
||||||
await ws.send_json({"error": "Internal Server Error"})
|
await ws.send_json({"detail": "Internal Server Error"})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user