Implement Permission Denied handling.

This commit is contained in:
Leo Vasanko 2025-08-30 18:38:48 -06:00
parent 16de7b5f1f
commit 4a0fbd8199
3 changed files with 54 additions and 1 deletions

View File

@ -5,6 +5,7 @@
<ProfileView v-if="store.currentView === 'profile'" />
<DeviceLinkView v-if="store.currentView === 'device-link'" />
<ResetView v-if="store.currentView === 'reset'" />
<PermissionDeniedView v-if="store.currentView === 'permission-denied'" />
</div>
</template>
@ -16,10 +17,15 @@ import LoginView from '@/components/LoginView.vue'
import ProfileView from '@/components/ProfileView.vue'
import DeviceLinkView from '@/components/DeviceLinkView.vue'
import ResetView from '@/components/ResetView.vue'
import PermissionDeniedView from '@/components/PermissionDeniedView.vue'
const store = useAuthStore()
onMounted(async () => {
// Detect restricted mode: any path not starting with /auth/
if (!location.pathname.startsWith('/auth/')) {
store.setRestrictedMode(true)
}
// Was an error message passed in the URL hash?
const message = location.hash.substring(1)
if (message) {

View File

@ -26,7 +26,10 @@ const handleLogin = async () => {
authStore.showMessage('Starting authentication...', 'info')
await authStore.authenticate()
authStore.showMessage('Authentication successful!', 'success', 2000)
if (location.pathname.startsWith('/auth/')) {
if (authStore.restrictedMode) {
// In restricted mode after successful auth show permission denied (no profile outside /auth/)
authStore.currentView = 'permission-denied'
} else if (location.pathname.startsWith('/auth/')) {
authStore.currentView = 'profile'
} else {
location.reload()

View File

@ -0,0 +1,44 @@
<template>
<div class="container">
<div class="view active">
<h1>🚫 Forbidden</h1>
<div v-if="authStore.userInfo?.authenticated" class="user-header">
<span class="user-emoji" aria-hidden="true">{{ userEmoji }}</span>
<span class="user-name">{{ displayName }}</span>
</div>
<p>You lack the permissions required for this page.</p>
<div class="actions">
<button class="btn-secondary" @click="back">Back</button>
<button class="btn-primary" @click="goAuth">Account</button>
<button class="btn-danger" @click="logout">Logout</button>
</div>
</div>
</div>
</template>
<script setup>
import { useAuthStore } from '@/stores/auth'
const authStore = useAuthStore()
const userEmoji = '👤' // Placeholder / could be extended later if backend provides one
const displayName = authStore.userInfo?.user?.user_name || 'User'
function goAuth() {
location.href = '/auth/'
}
function back() {
if (history.length > 1) history.back()
else authStore.currentView = 'login'
}
async function logout() {
await authStore.logout()
authStore.currentView = 'login'
}
</script>
<style scoped>
.user-header { display:flex; align-items:center; gap:.5rem; font-size:1.1rem; margin-bottom:.75rem; }
.user-emoji { font-size:1.5rem; line-height:1; }
.user-name { font-weight:600; }
.actions { margin-top:1.5rem; display:flex; gap:.5rem; flex-wrap:nowrap; }
.hint { font-size:.9rem; opacity:.85; }
</style>