Refactor to get user info from a single endpoint
This commit is contained in:
parent
3567b7802b
commit
19bcddca30
@ -17,12 +17,12 @@
|
|||||||
<div v-if="authStore.isLoading">
|
<div v-if="authStore.isLoading">
|
||||||
<p>Loading credentials...</p>
|
<p>Loading credentials...</p>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="userCredentialsData.credentials.length === 0">
|
<div v-else-if="authStore.currentCredentials.length === 0">
|
||||||
<p>No passkeys found.</p>
|
<p>No passkeys found.</p>
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<div
|
<div
|
||||||
v-for="credential in userCredentialsData.credentials"
|
v-for="credential in authStore.currentCredentials"
|
||||||
:key="credential.credential_id"
|
:key="credential.credential_id"
|
||||||
:class="['credential-item', { 'current-session': credential.is_current_session }]"
|
:class="['credential-item', { 'current-session': credential.is_current_session }]"
|
||||||
>
|
>
|
||||||
@ -84,36 +84,21 @@ import { formatDate } from '@/utils/helpers'
|
|||||||
import { registerCredential } from '@/utils/passkey'
|
import { registerCredential } from '@/utils/passkey'
|
||||||
|
|
||||||
const authStore = useAuthStore()
|
const authStore = useAuthStore()
|
||||||
const currentCredentials = ref([])
|
|
||||||
const userCredentialsData = ref({ credentials: [], aaguid_info: {} })
|
|
||||||
const updateInterval = ref(null)
|
const updateInterval = ref(null)
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
try {
|
try {
|
||||||
await authStore.loadUserInfo()
|
await authStore.loadUserInfo()
|
||||||
currentCredentials.value = await authStore.loadCredentials()
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
authStore.showMessage(`Failed to load user info: ${error.message}`, 'error')
|
authStore.showMessage(`Failed to load user info: ${error.message}`, 'error')
|
||||||
authStore.currentView = 'login'
|
authStore.currentView = 'login'
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch user credentials from the server
|
|
||||||
try {
|
|
||||||
const response = await fetch('/auth/user-credentials')
|
|
||||||
const result = await response.json()
|
|
||||||
console.log('Fetch Response:', result) // Log the entire response
|
|
||||||
if (result.error) throw new Error(result.error)
|
|
||||||
|
|
||||||
Object.assign(userCredentialsData.value, result) // Store the entire response
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Failed to fetch user credentials:', error)
|
|
||||||
}
|
|
||||||
|
|
||||||
updateInterval.value = setInterval(() => {
|
updateInterval.value = setInterval(() => {
|
||||||
// Trigger Vue reactivity to update formatDate fields
|
// Trigger Vue reactivity to update formatDate fields
|
||||||
authStore.currentUser = { ...authStore.currentUser }
|
authStore.currentUser = { ...authStore.currentUser }
|
||||||
userCredentialsData.value.credentials = [...userCredentialsData.value.credentials]
|
authStore.currentCredentials = [...authStore.currentCredentials]
|
||||||
}, 60000) // Update every minute
|
}, 60000) // Update every minute
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -124,12 +109,12 @@ onUnmounted(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const getCredentialAuthName = (credential) => {
|
const getCredentialAuthName = (credential) => {
|
||||||
const authInfo = userCredentialsData.value.aaguid_info[credential.aaguid]
|
const authInfo = authStore.aaguidInfo[credential.aaguid]
|
||||||
return authInfo ? authInfo.name : 'Unknown Authenticator'
|
return authInfo ? authInfo.name : 'Unknown Authenticator'
|
||||||
}
|
}
|
||||||
|
|
||||||
const getCredentialAuthIcon = (credential) => {
|
const getCredentialAuthIcon = (credential) => {
|
||||||
const authInfo = userCredentialsData.value.aaguid_info[credential.aaguid]
|
const authInfo = authStore.aaguidInfo[credential.aaguid]
|
||||||
if (!authInfo) return null
|
if (!authInfo) return null
|
||||||
|
|
||||||
const isDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches
|
const isDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches
|
||||||
@ -142,7 +127,7 @@ const addNewCredential = async () => {
|
|||||||
authStore.isLoading = true
|
authStore.isLoading = true
|
||||||
authStore.showMessage('Adding new passkey...', 'info')
|
authStore.showMessage('Adding new passkey...', 'info')
|
||||||
const result = await registerCredential()
|
const result = await registerCredential()
|
||||||
currentCredentials.value = await authStore.loadCredentials()
|
await authStore.loadUserInfo()
|
||||||
authStore.showMessage('New passkey added successfully!', 'success', 3000)
|
authStore.showMessage('New passkey added successfully!', 'success', 3000)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to add new passkey:', error)
|
console.error('Failed to add new passkey:', error)
|
||||||
@ -157,7 +142,6 @@ const deleteCredential = async (credentialId) => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await authStore.deleteCredential(credentialId)
|
await authStore.deleteCredential(credentialId)
|
||||||
currentCredentials.value = await authStore.loadCredentials()
|
|
||||||
authStore.showMessage('Passkey deleted successfully!', 'success', 3000)
|
authStore.showMessage('Passkey deleted successfully!', 'success', 3000)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
authStore.showMessage(`Failed to delete passkey: ${error.message}`, 'error')
|
authStore.showMessage(`Failed to delete passkey: ${error.message}`, 'error')
|
||||||
|
@ -5,6 +5,8 @@ export const useAuthStore = defineStore('auth', {
|
|||||||
state: () => ({
|
state: () => ({
|
||||||
// Auth State
|
// Auth State
|
||||||
currentUser: null,
|
currentUser: null,
|
||||||
|
currentCredentials: [],
|
||||||
|
aaguidInfo: {},
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
|
|
||||||
// UI State
|
// UI State
|
||||||
@ -87,19 +89,8 @@ export const useAuthStore = defineStore('auth', {
|
|||||||
if (result.error) throw new Error(`Server: ${result.error}`)
|
if (result.error) throw new Error(`Server: ${result.error}`)
|
||||||
|
|
||||||
this.currentUser = result.user
|
this.currentUser = result.user
|
||||||
},
|
this.currentCredentials = result.credentials || []
|
||||||
async loadCredentials() {
|
|
||||||
this.isLoading = true
|
|
||||||
try {
|
|
||||||
const response = await fetch('/auth/user-credentials')
|
|
||||||
const result = await response.json()
|
|
||||||
if (result.error) throw new Error(`Server: ${result.error}`)
|
|
||||||
|
|
||||||
this.currentCredentials = result.credentials
|
|
||||||
this.aaguidInfo = result.aaguid_info || {}
|
this.aaguidInfo = result.aaguid_info || {}
|
||||||
} finally {
|
|
||||||
this.isLoading = false
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
async deleteCredential(credentialId) {
|
async deleteCredential(credentialId) {
|
||||||
const response = await fetch('/auth/delete-credential', {
|
const response = await fetch('/auth/delete-credential', {
|
||||||
@ -112,7 +103,7 @@ export const useAuthStore = defineStore('auth', {
|
|||||||
const result = await response.json()
|
const result = await response.json()
|
||||||
if (result.error) throw new Error(`Server: ${result.error}`)
|
if (result.error) throw new Error(`Server: ${result.error}`)
|
||||||
|
|
||||||
await this.loadCredentials()
|
await this.loadUserInfo()
|
||||||
},
|
},
|
||||||
async logout() {
|
async logout() {
|
||||||
try {
|
try {
|
||||||
|
@ -23,28 +23,7 @@ from .session_manager import (
|
|||||||
|
|
||||||
|
|
||||||
async def get_user_info(request: Request) -> dict:
|
async def get_user_info(request: Request) -> dict:
|
||||||
"""Get user information from session cookie."""
|
"""Get user information and credentials from session cookie."""
|
||||||
try:
|
|
||||||
user = await get_current_user(request)
|
|
||||||
if not user:
|
|
||||||
return {"error": "Not authenticated"}
|
|
||||||
|
|
||||||
return {
|
|
||||||
"status": "success",
|
|
||||||
"user": {
|
|
||||||
"user_id": str(user.user_id),
|
|
||||||
"user_name": user.user_name,
|
|
||||||
"created_at": user.created_at.isoformat() if user.created_at else None,
|
|
||||||
"last_seen": user.last_seen.isoformat() if user.last_seen else None,
|
|
||||||
"visits": user.visits,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
except Exception as e:
|
|
||||||
return {"error": f"Failed to get user info: {str(e)}"}
|
|
||||||
|
|
||||||
|
|
||||||
async def get_user_credentials(request: Request) -> dict:
|
|
||||||
"""Get all credentials for a user using session cookie."""
|
|
||||||
try:
|
try:
|
||||||
user = await get_current_user(request)
|
user = await get_current_user(request)
|
||||||
if not user:
|
if not user:
|
||||||
@ -98,11 +77,18 @@ async def get_user_credentials(request: Request) -> dict:
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
"status": "success",
|
"status": "success",
|
||||||
|
"user": {
|
||||||
|
"user_id": str(user.user_id),
|
||||||
|
"user_name": user.user_name,
|
||||||
|
"created_at": user.created_at.isoformat() if user.created_at else None,
|
||||||
|
"last_seen": user.last_seen.isoformat() if user.last_seen else None,
|
||||||
|
"visits": user.visits,
|
||||||
|
},
|
||||||
"credentials": credentials,
|
"credentials": credentials,
|
||||||
"aaguid_info": aaguid_info,
|
"aaguid_info": aaguid_info,
|
||||||
}
|
}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return {"error": f"Failed to get credentials: {str(e)}"}
|
return {"error": f"Failed to get user info: {str(e)}"}
|
||||||
|
|
||||||
|
|
||||||
async def refresh_token(request: Request, response: Response) -> dict:
|
async def refresh_token(request: Request, response: Response) -> dict:
|
||||||
|
@ -30,7 +30,6 @@ from fastapi.staticfiles import StaticFiles
|
|||||||
from ..db import sql
|
from ..db import sql
|
||||||
from .api_handlers import (
|
from .api_handlers import (
|
||||||
delete_credential,
|
delete_credential,
|
||||||
get_user_credentials,
|
|
||||||
get_user_info,
|
get_user_info,
|
||||||
logout,
|
logout,
|
||||||
refresh_token,
|
refresh_token,
|
||||||
@ -55,21 +54,12 @@ app = FastAPI(title="Passkey Auth", lifespan=lifespan)
|
|||||||
app.mount("/auth/ws", ws_app)
|
app.mount("/auth/ws", ws_app)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@app.get("/auth/user-info")
|
@app.get("/auth/user-info")
|
||||||
async def api_get_user_info(request: Request):
|
async def api_get_user_info(request: Request):
|
||||||
"""Get user information from session cookie."""
|
"""Get user information and credentials from session cookie."""
|
||||||
return await get_user_info(request)
|
return await get_user_info(request)
|
||||||
|
|
||||||
|
|
||||||
@app.get("/auth/user-credentials")
|
|
||||||
async def api_get_user_credentials(request: Request):
|
|
||||||
"""Get all credentials for a user using session cookie."""
|
|
||||||
return await get_user_credentials(request)
|
|
||||||
|
|
||||||
|
|
||||||
@app.post("/auth/refresh-token")
|
@app.post("/auth/refresh-token")
|
||||||
async def api_refresh_token(request: Request, response: Response):
|
async def api_refresh_token(request: Request, response: Response):
|
||||||
"""Refresh the session token."""
|
"""Refresh the session token."""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user