auth
This commit is contained in:
122
web/src/App.vue
Normal file
122
web/src/App.vue
Normal file
@@ -0,0 +1,122 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onBeforeUnmount } from 'vue'
|
||||
import Splitter from 'primevue/splitter'
|
||||
import SplitterPanel from 'primevue/splitterpanel'
|
||||
import ChartView from './components/ChartView.vue'
|
||||
import ChatPanel from './components/ChatPanel.vue'
|
||||
import LoginScreen from './components/LoginScreen.vue'
|
||||
import { useOrderStore } from './stores/orders'
|
||||
import { useChartStore } from './stores/chart'
|
||||
import { useStateSync } from './composables/useStateSync'
|
||||
import { wsManager } from './composables/useWebSocket'
|
||||
|
||||
const isAuthenticated = ref(false)
|
||||
const needsConfirmation = ref(false)
|
||||
const authError = ref<string>()
|
||||
let stateSyncCleanup: (() => void) | null = null
|
||||
|
||||
// Check if we need password confirmation on first load
|
||||
onMounted(async () => {
|
||||
// Check if secrets store is initialized by trying to fetch a status endpoint
|
||||
// For now, just default to false (user will see login screen)
|
||||
needsConfirmation.value = false
|
||||
})
|
||||
|
||||
const handleAuthenticate = async (
|
||||
password: string,
|
||||
confirmPassword?: string,
|
||||
newPassword?: string,
|
||||
confirmNewPassword?: string
|
||||
) => {
|
||||
authError.value = undefined
|
||||
|
||||
try {
|
||||
const result = await wsManager.connect(password, confirmPassword, newPassword, confirmNewPassword)
|
||||
|
||||
if (result.success) {
|
||||
isAuthenticated.value = true
|
||||
|
||||
// Initialize state sync after successful authentication
|
||||
const orderStore = useOrderStore()
|
||||
const chartStore = useChartStore()
|
||||
const stateSync = useStateSync({
|
||||
OrderStore: orderStore,
|
||||
ChartStore: chartStore
|
||||
})
|
||||
stateSyncCleanup = stateSync.cleanup
|
||||
} else {
|
||||
authError.value = result.message
|
||||
|
||||
// If server says we need confirmation, update the flag
|
||||
if (result.needsConfirmation) {
|
||||
needsConfirmation.value = true
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
authError.value = 'Connection failed'
|
||||
console.error('Authentication error:', err)
|
||||
}
|
||||
}
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if (stateSyncCleanup) {
|
||||
stateSyncCleanup()
|
||||
}
|
||||
wsManager.disconnect()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="app-container dark">
|
||||
<LoginScreen
|
||||
v-if="!isAuthenticated"
|
||||
:needs-confirmation="needsConfirmation"
|
||||
:error-message="authError"
|
||||
@authenticate="handleAuthenticate"
|
||||
/>
|
||||
<Splitter v-else class="main-splitter">
|
||||
<SplitterPanel :size="62" :minSize="40" class="chart-panel">
|
||||
<ChartView />
|
||||
</SplitterPanel>
|
||||
<SplitterPanel :size="38" :minSize="20" class="chat-panel">
|
||||
<ChatPanel />
|
||||
</SplitterPanel>
|
||||
</Splitter>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.app-container {
|
||||
width: 100vw !important;
|
||||
height: 100vh !important;
|
||||
overflow: hidden;
|
||||
background: var(--p-surface-0);
|
||||
}
|
||||
|
||||
.main-splitter {
|
||||
height: 100vh !important;
|
||||
}
|
||||
|
||||
.main-splitter :deep(.p-splitter-gutter) {
|
||||
background: var(--p-surface-100);
|
||||
}
|
||||
|
||||
.main-splitter :deep(.p-splitter-gutter-handle) {
|
||||
background: var(--p-primary-color);
|
||||
}
|
||||
|
||||
.chart-panel,
|
||||
.chat-panel {
|
||||
height: 100% !important;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.chart-panel :deep(.p-splitter-panel-content),
|
||||
.chat-panel :deep(.p-splitter-panel-content) {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user