Files
bssapp/ui/src/stores/permissionStore.js
2026-02-19 01:34:56 +03:00

206 lines
4.0 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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
}
}
})