Skip to content

Commit beef3fc

Browse files
Centralize authentication state in Pinia
1 parent 5b13383 commit beef3fc

3 files changed

Lines changed: 14 additions & 5 deletions

File tree

‎web/src/main.ts‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { createApp } from 'vue'; import { createPinia } from 'pinia'; import { createRouter,createWebHistory } from 'vue-router'; import App from './App.vue'; import './tailwind.css'; import './style.css';
1+
import { createApp } from 'vue'; import { createPinia } from 'pinia'; import { createRouter,createWebHistory } from 'vue-router'; import App from './App.vue'; import {useAuthStore} from './stores/auth'; import './tailwind.css'; import './style.css';
22
const router=createRouter({history:createWebHistory(),routes:[{path:'/',component:()=>import('./views/Dashboard.vue'),meta:{auth:true}},{path:'/login',component:()=>import('./views/Login.vue')},{path:'/setup',component:()=>import('./views/Setup.vue')},{path:'/projects',component:()=>import('./views/Projects.vue'),meta:{auth:true}},{path:'/projects/:id',component:()=>import('./views/ProjectDetail.vue'),meta:{auth:true}},{path:'/infrastructure',component:()=>import('./views/Infrastructure.vue'),meta:{auth:true}},{path:'/settings',component:()=>import('./views/Settings.vue'),meta:{auth:true}} ]});
33
router.addRoute({path:'/activity',component:()=>import('./views/Activity.vue'),meta:{auth:true}});
4-
router.beforeEach(async(to)=>{if(to.path==='/setup'||to.path==='/login')return true;const setup=await fetch('/api/v1/setup/status').then(r=>r.json()).catch(()=>({needs_setup:false}));if(setup.needs_setup)return '/setup';if(!(await fetch('/api/v1/me')).ok)return `/login?redirect=${encodeURIComponent(to.fullPath)}`;return true});
5-
createApp(App).use(createPinia()).use(router).mount('#app');
4+
const pinia=createPinia();const auth=useAuthStore(pinia);router.beforeEach(async(to)=>{if(to.path==='/setup'||to.path==='/login')return true;const setup=await fetch('/api/v1/setup/status').then(r=>r.json()).catch(()=>({needs_setup:false}));if(setup.needs_setup)return '/setup';if(!(await auth.load()))return `/login?redirect=${encodeURIComponent(to.fullPath)}`;return true});
5+
createApp(App).use(pinia).use(router).mount('#app');

‎web/src/stores/auth.ts‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { defineStore } from 'pinia';
2+
3+
export const useAuthStore = defineStore('auth', {
4+
state: () => ({ user: null as null | { id: number; name: string; email: string; role: string }, loaded: false }),
5+
actions: {
6+
async load() { const response = await fetch('/api/v1/me'); this.user = response.ok ? await response.json() : null; this.loaded = true; return this.user; },
7+
clear() { this.user = null; this.loaded = true; }
8+
}
9+
});

‎web/src/views/Settings.vue‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
<script setup lang="ts">import {onMounted,ref} from 'vue';import {useRouter} from 'vue-router';const router=useRouter();const me=ref<any>({});onMounted(async()=>me.value=await (await fetch('/api/v1/me')).json());const logout=async()=>{await fetch('/api/v1/auth/logout',{method:'POST'});router.push('/login')}</script>
2-
<template><div class="hero"><div><p class="kicker">ACCOUNT</p><h1>Settings</h1><p class="muted">Manage this local StackHost administrator.</p></div></div><div class="status"><div><strong>{{me.name}}</strong><p>{{me.email}} · {{me.role}}</p></div></div><button class="secondary" @click="logout">Sign out</button></template>
1+
<script setup lang="ts">import {useRouter} from 'vue-router';import {useAuthStore} from '../stores/auth';const router=useRouter(),auth=useAuthStore();const logout=async()=>{await fetch('/api/v1/auth/logout',{method:'POST'});auth.clear();router.push('/login')}</script>
2+
<template><div class="hero"><div><p class="kicker">ACCOUNT</p><h1>Settings</h1><p class="muted">Manage this local StackHost administrator.</p></div></div><div class="status"><div><strong>{{auth.user?.name}}</strong><p>{{auth.user?.email}} · {{auth.user?.role}}</p></div></div><button class="secondary" @click="logout">Sign out</button></template>

0 commit comments

Comments
 (0)