Files
bssapp/ui/src/stores/permissionStore.js
T

206 lines
4.0 KiB
JavaScript

import { defineStore } from 'pinia'
import api from 'src/services/api'
import { useAuthStore } from 'stores/authStore'
const ACTION_ALIASES = {
read: ['read', 'view'],
view: ['read', 'view'],
write: ['write', 'insert'],
insert: ['write', 'insert'],
update: ['update'],
delete: ['delete'],
export: ['export']
}
function normalizeToken (value) {
return String(value || '').trim().toLowerCase()
}
function actionCandidates (action) {
const key = normalizeToken(action)
return ACTION_ALIASES[key] || [key]
}
export const usePermissionStore = defineStore('permission', {
state: () => ({
// API route yetkileri
routes: [],
// module+action matrix
matrix: [],
loaded: false
}),
getters: {
/* ================= ADMIN ================= */
isAdmin () {
const auth = useAuthStore()
return auth.isAdmin === true
},
/* ================= API ROUTE ================= */
hasApiPermission: (state) => (apiPathOrPerm) => {
const auth = useAuthStore()
if (auth.isAdmin) return true
if (!state.loaded) return false
if (!apiPathOrPerm) return true
// ============================
// 1️⃣ MODULE:ACTION GELDİYSE
// ============================
if (apiPathOrPerm.includes(':')) {
const [moduleRaw, actionRaw] = apiPathOrPerm.split(':')
const module = normalizeToken(moduleRaw)
const actions = actionCandidates(actionRaw)
return state.matrix.some(p =>
normalizeToken(p.module) === module &&
actions.includes(normalizeToken(p.action)) &&
p.allowed === true
)
}
// ============================
// 2️⃣ API PATH GELDİYSE
// ===========================
const apiPath = apiPathOrPerm
// exact match
if (state.routes.some(p =>
p.route === apiPath && p.can_access
)) {
return true
}
// /{id} normalize
const normalized = apiPath
.replace(/\/\d+/g, '/{id}')
if (state.routes.some(p =>
p.route === normalized && p.can_access
)) {
return true
}
// prefix
return state.routes.some(p =>
p.can_access && apiPath.startsWith(p.route)
)
},
/* ================= MODULE ================= */
hasModule: (state) => (module) => {
const auth = useAuthStore()
const moduleKey = normalizeToken(module)
if (auth.isAdmin) return true
if (!state.loaded) return false
return state.matrix.some(p =>
normalizeToken(p.module) === moduleKey &&
p.allowed === true
)
},
/* ================= ACTION ================= */
hasPermission: (state) => (module, action) => {
const auth = useAuthStore()
const moduleKey = normalizeToken(module)
const actions = actionCandidates(action)
if (auth.isAdmin) return true
if (!state.loaded) return false
return state.matrix.some(p =>
normalizeToken(p.module) === moduleKey &&
actions.includes(normalizeToken(p.action)) &&
p.allowed === true
)
}
},
actions: {
async fetchPermissions () {
const auth = useAuthStore()
if (auth.isAdmin) {
this.routes = []
this.matrix = []
this.loaded = true
return
}
try {
const [routesRes, effRes] = await Promise.all([
api.get('/permissions/routes'),
api.get('/permissions/effective')
])
this.routes = routesRes.data || []
this.matrix = effRes.data || []
console.group('🔐 PERMISSION DEBUG')
console.log('API ROUTES:', this.routes)
console.log('EFFECTIVE MATRIX:', this.matrix)
console.groupEnd()
} catch (err) {
console.error('❌ Permission load failed', err)
this.routes = []
this.matrix = []
} finally {
this.loaded = true
}
},
clear () {
this.routes = []
this.matrix = []
this.loaded = false
}
}
})