Integrate host app to main app (WIP).
This commit is contained in:
+37
-3
@@ -2,7 +2,8 @@
|
|||||||
<div class="app-shell">
|
<div class="app-shell">
|
||||||
<StatusMessage />
|
<StatusMessage />
|
||||||
<main class="app-main">
|
<main class="app-main">
|
||||||
<ProfileView v-if="authenticated" />
|
<HostProfileView v-if="authenticated && isHostMode" :initializing="loading" />
|
||||||
|
<ProfileView v-else-if="authenticated" />
|
||||||
<LoadingView v-else-if="loading" :message="loadingMessage" />
|
<LoadingView v-else-if="loading" :message="loadingMessage" />
|
||||||
<AuthRequiredMessage v-else-if="showBackMessage" @reload="reloadPage" />
|
<AuthRequiredMessage v-else-if="showBackMessage" @reload="reloadPage" />
|
||||||
</main>
|
</main>
|
||||||
@@ -10,11 +11,12 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, onUnmounted, ref } from 'vue'
|
import { computed, onMounted, onUnmounted, ref } from 'vue'
|
||||||
import { useAuthStore } from '@/stores/auth'
|
import { useAuthStore } from '@/stores/auth'
|
||||||
import { apiJson, getAuthIframeUrl } from '@/utils/api'
|
import { apiJson, getAuthIframeUrl } from '@/utils/api'
|
||||||
import StatusMessage from '@/components/StatusMessage.vue'
|
import StatusMessage from '@/components/StatusMessage.vue'
|
||||||
import ProfileView from '@/components/ProfileView.vue'
|
import ProfileView from '@/components/ProfileView.vue'
|
||||||
|
import HostProfileView from '@/components/HostProfileView.vue'
|
||||||
import LoadingView from '@/components/LoadingView.vue'
|
import LoadingView from '@/components/LoadingView.vue'
|
||||||
import AuthRequiredMessage from '@/components/AccessDenied.vue'
|
import AuthRequiredMessage from '@/components/AccessDenied.vue'
|
||||||
|
|
||||||
@@ -23,6 +25,29 @@ const loading = ref(true)
|
|||||||
const loadingMessage = ref('Loading...')
|
const loadingMessage = ref('Loading...')
|
||||||
const authenticated = ref(false)
|
const authenticated = ref(false)
|
||||||
const showBackMessage = ref(false)
|
const showBackMessage = ref(false)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalize a host string for comparison (lowercase, strip default ports).
|
||||||
|
*/
|
||||||
|
function normalizeHost(raw) {
|
||||||
|
if (!raw) return null
|
||||||
|
const trimmed = raw.trim().toLowerCase()
|
||||||
|
if (!trimmed) return null
|
||||||
|
// Remove default ports
|
||||||
|
return trimmed.replace(/:80$/, '').replace(/:443$/, '')
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Host mode is active when an auth_host is configured AND the current host differs from it.
|
||||||
|
* In host mode, we show a limited profile view with logout and link to full profile.
|
||||||
|
*/
|
||||||
|
const isHostMode = computed(() => {
|
||||||
|
const authHost = store.settings?.auth_host
|
||||||
|
if (!authHost) return false
|
||||||
|
const currentHost = normalizeHost(window.location.host)
|
||||||
|
const configuredHost = normalizeHost(authHost)
|
||||||
|
return currentHost !== configuredHost
|
||||||
|
})
|
||||||
let validationTimer = null
|
let validationTimer = null
|
||||||
let authIframe = null
|
let authIframe = null
|
||||||
|
|
||||||
@@ -147,7 +172,16 @@ onMounted(async () => {
|
|||||||
|
|
||||||
// Load settings
|
// Load settings
|
||||||
await store.loadSettings()
|
await store.loadSettings()
|
||||||
if (store.settings?.rp_name) document.title = store.settings.rp_name
|
|
||||||
|
// Set appropriate page title based on mode
|
||||||
|
const rpName = store.settings?.rp_name
|
||||||
|
if (rpName) {
|
||||||
|
// In host mode, show "account summary" style title
|
||||||
|
// Settings are loaded but isHostMode depends on them, so check here
|
||||||
|
const authHost = store.settings?.auth_host
|
||||||
|
const inHostMode = authHost && normalizeHost(window.location.host) !== normalizeHost(authHost)
|
||||||
|
document.title = inHostMode ? `${rpName} · Account summary` : rpName
|
||||||
|
}
|
||||||
|
|
||||||
// Try to load user info
|
// Try to load user info
|
||||||
const success = await loadUserInfo()
|
const success = await loadUserInfo()
|
||||||
|
|||||||
@@ -76,14 +76,9 @@ async def restricted_view():
|
|||||||
async def frontapp(request: Request, response: Response, auth=AUTH_COOKIE):
|
async def frontapp(request: Request, response: Response, auth=AUTH_COOKIE):
|
||||||
"""Serve the user profile app.
|
"""Serve the user profile app.
|
||||||
|
|
||||||
|
The frontend handles mode detection (host mode vs full profile) based on settings.
|
||||||
Access control is handled via APIs.
|
Access control is handled via APIs.
|
||||||
"""
|
"""
|
||||||
cfg_host = hostutil.configured_auth_host()
|
|
||||||
if cfg_host:
|
|
||||||
cur_host = hostutil.normalize_host(request.headers.get("host"))
|
|
||||||
cfg_normalized = hostutil.normalize_host(cfg_host)
|
|
||||||
if cur_host and cfg_normalized and cur_host != cfg_normalized:
|
|
||||||
return Response(*await frontend.read("/int/host/index.html"))
|
|
||||||
return Response(*await frontend.read("/auth/index.html"))
|
return Response(*await frontend.read("/auth/index.html"))
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user