add user privileges & add translations

This commit is contained in:
2026-04-20 19:12:27 +03:00
parent f16a830eb2
commit fc96a95335
17 changed files with 1073 additions and 426 deletions

View File

@@ -1,4 +1,6 @@
import { createRouter, createWebHistory } from 'vue-router'
import { useUserStore } from '../stores/user'
import { useSettingsStore } from '../stores/settings'
import Login from '../views/auth/Login.vue'
import Setup from '../views/auth/Setup.vue'
import Register from '../views/auth/Register.vue'
@@ -6,60 +8,29 @@ import Dashboard from '../views/Dashboard.vue'
import Users from '../views/Users.vue'
import Restaurants from '../views/Restaurants.vue'
import AdminSettings from '../views/AdminSettings.vue'
import Profile from '../views/Profile.vue'
import NotFound from '../views/NotFound.vue'
import { useSettingsStore } from '../stores/settings'
const routes = [
{ path: '/login', component: Login, meta: { title: 'Login', requiresAuth: false } },
{ path: '/register', component: Register, meta: { title: 'Register', requiresAuth: false } },
{ path: '/setup', component: Setup, meta: { title: 'Setup', requiresAuth: false } },
{
path: '/',
redirect: '/dashboard'
},
{
path: '/dashboard',
component: Dashboard,
meta: { requiresAuth: true, title: 'Dashboard' }
},
{
path: '/users',
component: Users,
meta: { requiresAuth: true, title: 'Users' }
},
{
path: '/restaurants',
component: Restaurants,
meta: { requiresAuth: true, title: 'Restaurants' }
},
{
path: '/settings',
component: AdminSettings,
meta: { requiresAuth: true, title: 'Settings' }
},
{
path: '/:pathMatch(.*)*',
name: 'NotFound',
component: NotFound,
meta: { title: 'Page Not Found', requiresAuth: false }
}
{ path: '/', redirect: '/dashboard' },
{ path: '/dashboard', component: Dashboard, meta: { requiresAuth: true, title: 'Dashboard' } },
{ path: '/users', component: Users, meta: { requiresAuth: true, requiresAdmin: true, title: 'Users' } },
{ path: '/restaurants', component: Restaurants, meta: { requiresAuth: true, title: 'Restaurants' } },
{ path: '/settings', component: AdminSettings, meta: { requiresAuth: true, requiresAdmin: true, title: 'Settings' } },
{ path: '/profile', component: Profile, meta: { requiresAuth: true, title: 'Profile' } },
{ path: '/:pathMatch(.*)*', name: 'NotFound', component: NotFound, meta: { title: 'Page Not Found', requiresAuth: false } }
]
const router = createRouter({
history: createWebHistory(),
routes
})
const router = createRouter({ history: createWebHistory(), routes })
router.beforeEach(async (to, from, next) => {
// Загружаем настройки приложения, если они ещё не загружены
const settings = useSettingsStore()
if (!settings.siteName) {
await settings.loadSettings()
}
if (!settings.siteName) await settings.loadSettings()
// Устанавливаем заголовок страницы с использованием site_name
const pageTitle = to.meta.title ? `${to.meta.title} | ${settings.siteName}` : settings.siteName
document.title = pageTitle
document.title = to.meta.title ? `${to.meta.title} | ${settings.siteName}` : settings.siteName
// Проверка необходимости установки (setup)
try {
@@ -69,44 +40,33 @@ router.beforeEach(async (to, from, next) => {
next('/setup')
return
}
} catch (e) {
console.error('Failed to check status', e)
} catch (e) { console.error('Failed to check status', e) }
const userStore = useUserStore()
// Если профиль ещё не загружен загружаем
if (userStore.role === '') {
await userStore.fetchProfile()
}
// Проверка, что залогиненный пользователь не может зайти на страницу логина
if (to.path === '/login') {
try {
const meRes = await fetch('/api/admin/me')
if (meRes.ok) {
next('/dashboard')
return
}
} catch (e) {
// игнорируем ошибку, продолжаем
}
// Если уже залогинены и пытаемся зайти на login/register редирект на дашборд
if (userStore.id && (to.path === '/login' || to.path === '/register')) {
next('/dashboard')
return
}
// Проверка доступности регистрации
if (to.path === '/register') {
if (!settings.enableRegistration) {
next('/login')
return
}
if (to.path === '/register' && !settings.enableRegistration) {
next('/login')
return
}
// Проверка аутентификации для защищённых маршрутов
const requiresAuth = to.matched.some(record => record.meta.requiresAuth)
if (requiresAuth) {
try {
const res = await fetch('/api/admin/me')
if (!res.ok) {
next('/login')
} else {
next()
}
} catch {
next('/login')
}
const requiresAdmin = to.matched.some(record => record.meta.requiresAdmin)
if (requiresAuth && !userStore.id) {
next('/login')
} else if (requiresAdmin && userStore.role !== 'admin') {
next('/dashboard')
} else {
next()
}