feat: add auth routing and role guards
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
<script setup lang="ts">import { RouterView } from 'vue-router';</script>
|
||||
<template><RouterView/></template>
|
||||
@@ -1,5 +1,6 @@
|
||||
import { createApp } from 'vue'
|
||||
import './style.css'
|
||||
import './enhancements.css'
|
||||
import App from './App.vue'
|
||||
createApp(App).mount('#app')
|
||||
import Root from './Root.vue'
|
||||
import router from './router'
|
||||
createApp(Root).use(router).mount('#app')
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import App from './App.vue'
|
||||
import { getCurrentUser } from './services/auth'
|
||||
import type { UserRole } from './types/auth'
|
||||
|
||||
let role:UserRole|undefined
|
||||
const router=createRouter({history:createWebHistory(),routes:[
|
||||
{path:'/',component:App},
|
||||
{path:'/login',component:()=>import('./views/LoginView.vue'),meta:{public:true}},
|
||||
{path:'/register',component:()=>import('./views/RegisterView.vue'),meta:{public:true}},
|
||||
{path:'/profile',component:()=>import('./views/ProfileView.vue')},
|
||||
{path:'/admin',component:()=>import('./views/AdminView.vue'),meta:{role:'admin'}},
|
||||
]})
|
||||
router.beforeEach(async to=>{if(to.meta.public)return true;try{role=(await getCurrentUser()).role}catch{return {path:'/login',query:{redirect:to.fullPath}}}if(to.meta.role&&role!==to.meta.role)return {path:'/profile',query:{forbidden:'1'}};return true})
|
||||
export default router
|
||||
@@ -0,0 +1 @@
|
||||
<script setup lang="ts">import { onMounted,ref } from 'vue';import { getUsers } from '../services/auth';const users=ref<any[]>([]),error=ref('');onMounted(async()=>{try{users.value=await getUsers()}catch(e){error.value=e instanceof Error?e.message:'无管理员权限'}});</script><template><main><h1>管理员用户管理</h1><p v-if="error">{{error}}</p><table v-else><tr><th>用户名</th><th>邮箱</th><th>角色</th></tr><tr v-for="u in users" :key="u.id"><td>{{u.username}}</td><td>{{u.email}}</td><td>{{u.role}}</td></tr></table></main></template>
|
||||
@@ -0,0 +1 @@
|
||||
<script setup lang="ts">import { ref } from 'vue';import { useRoute,useRouter } from 'vue-router';import { login } from '../services/auth';const username=ref(''),password=ref(''),error=ref(''),router=useRouter(),route=useRoute();async function submit(){try{await login({username:username.value,password:password.value});await router.replace(typeof route.query.redirect==='string'?route.query.redirect:'/')}catch(e){error.value=e instanceof Error?e.message:'登录失败'}}</script><template><main><h1>登录</h1><form @submit.prevent="submit"><input v-model="username" autocomplete="username" required placeholder="用户名"><input v-model="password" type="password" autocomplete="current-password" required placeholder="密码"><p v-if="error">{{error}}</p><button>登录</button></form><RouterLink to="/register">注册账户</RouterLink></main></template>
|
||||
@@ -0,0 +1 @@
|
||||
<script setup lang="ts">import { onMounted,ref } from 'vue';import { getCurrentUser,logout } from '../services/auth';import { useRouter } from 'vue-router';const user=ref<any>(),error=ref(''),router=useRouter();onMounted(async()=>{try{user.value=await getCurrentUser()}catch(e){error.value=e instanceof Error?e.message:'无法读取资料'}});async function signOut(){await logout();router.replace('/login')}</script><template><main><h1>个人中心</h1><p v-if="error">{{error}}</p><dl v-else-if="user"><dt>用户名</dt><dd>{{user.username}}</dd><dt>昵称</dt><dd>{{user.nickname||'未设置'}}</dd><dt>邮箱</dt><dd>{{user.email||'未设置'}}</dd><dt>角色</dt><dd>{{user.role}}</dd></dl><button @click="signOut">退出登录</button></main></template>
|
||||
@@ -0,0 +1 @@
|
||||
<script setup lang="ts">import { ref } from 'vue';import { useRouter } from 'vue-router';import { register } from '../services/auth';const username=ref(''),password=ref(''),error=ref(''),router=useRouter();async function submit(){try{await register({username:username.value,password:password.value});await router.push('/login')}catch(e){error.value=e instanceof Error?e.message:'注册失败'}}</script><template><main><h1>注册</h1><form @submit.prevent="submit"><input v-model="username" required minlength="3" placeholder="用户名"><input v-model="password" required minlength="15" type="password" placeholder="至少 15 位密码"><p v-if="error">{{error}}</p><button>注册</button></form></main></template>
|
||||
Reference in New Issue
Block a user