Files
InvoiceShelf/resources/scripts/composables/use-permissions.ts
Darko Gjorgjijoski 71388ec6a5 Rename resources/scripts-v2 to resources/scripts and drop @v2 alias
Now that the legacy v1 frontend (commit 064bdf53) is gone, the v2 directory is the only frontend and the v2 suffix is just noise. Renames resources/scripts-v2 to resources/scripts via git mv (so git records the move as renames, preserving blame and log --follow), then bulk-rewrites the 152 files that imported via @v2/... to use @/scripts/... instead. The existing @ alias (resources/) covers the new path with no extra config needed.

Drops the now-unused @v2 alias from vite.config.js and points the laravel-vite-plugin entry at resources/scripts/main.ts. Updates the only blade reference (resources/views/app.blade.php) to match. The package.json test script (eslint ./resources/scripts) automatically targets the right place after the rename without any edit.

Verified: npm run build exits clean and the Vite warning lines now reference resources/scripts/plugins/i18n.ts, confirming every import resolved through the new path. git log --follow on any moved file walks back through its scripts-v2 history.
2026-04-07 12:50:16 +02:00

161 lines
5.7 KiB
TypeScript

import { ref, computed } from 'vue'
import type { Ref, ComputedRef } from 'vue'
import { ABILITIES } from '@/scripts/config/abilities'
import type { Ability } from '@/scripts/config/abilities'
export interface UserAbility {
name: string
[key: string]: unknown
}
export interface UsePermissionsReturn {
currentAbilities: Ref<UserAbility[]>
isOwner: Ref<boolean>
isSuperAdmin: Ref<boolean>
setAbilities: (abilities: UserAbility[]) => void
setOwner: (owner: boolean) => void
setSuperAdmin: (superAdmin: boolean) => void
hasAbility: (ability: Ability | Ability[]) => boolean
hasAllAbilities: (abilities: Ability[]) => boolean
canViewCustomer: ComputedRef<boolean>
canCreateCustomer: ComputedRef<boolean>
canEditCustomer: ComputedRef<boolean>
canDeleteCustomer: ComputedRef<boolean>
canViewInvoice: ComputedRef<boolean>
canCreateInvoice: ComputedRef<boolean>
canEditInvoice: ComputedRef<boolean>
canDeleteInvoice: ComputedRef<boolean>
canViewEstimate: ComputedRef<boolean>
canCreateEstimate: ComputedRef<boolean>
canEditEstimate: ComputedRef<boolean>
canDeleteEstimate: ComputedRef<boolean>
canViewPayment: ComputedRef<boolean>
canCreatePayment: ComputedRef<boolean>
canEditPayment: ComputedRef<boolean>
canDeletePayment: ComputedRef<boolean>
canViewExpense: ComputedRef<boolean>
canCreateExpense: ComputedRef<boolean>
canEditExpense: ComputedRef<boolean>
canDeleteExpense: ComputedRef<boolean>
canViewDashboard: ComputedRef<boolean>
canViewFinancialReport: ComputedRef<boolean>
}
const currentAbilities = ref<UserAbility[]>([])
const isOwner = ref<boolean>(false)
const isSuperAdmin = ref<boolean>(false)
/**
* Composable for managing user permissions and abilities.
* Extracted from the user store's hasAbilities/hasAllAbilities logic,
* with typed convenience computed properties for common CRUD checks.
*/
export function usePermissions(): UsePermissionsReturn {
function setAbilities(abilities: UserAbility[]): void {
currentAbilities.value = abilities
}
function setOwner(owner: boolean): void {
isOwner.value = owner
}
function setSuperAdmin(superAdmin: boolean): void {
isSuperAdmin.value = superAdmin
}
/**
* Check if the current user has a given ability or any of the given abilities.
* A wildcard ability ('*') grants access to everything.
*
* @param ability - A single ability string or array of abilities
* @returns True if the user has the ability
*/
function hasAbility(ability: Ability | Ability[]): boolean {
return !!currentAbilities.value.find((ab) => {
if (ab.name === '*') return true
if (typeof ability === 'string') {
return ab.name === ability
}
return !!ability.find((p) => ab.name === p)
})
}
/**
* Check if the current user has ALL of the given abilities.
*
* @param abilities - Array of abilities that must all be present
* @returns True if the user has every listed ability
*/
function hasAllAbilities(abilities: Ability[]): boolean {
return abilities.every((ability) =>
currentAbilities.value.some(
(ab) => ab.name === '*' || ab.name === ability
)
)
}
// Convenience computed properties for common permission checks
const canViewCustomer = computed<boolean>(() => hasAbility(ABILITIES.VIEW_CUSTOMER))
const canCreateCustomer = computed<boolean>(() => hasAbility(ABILITIES.CREATE_CUSTOMER))
const canEditCustomer = computed<boolean>(() => hasAbility(ABILITIES.EDIT_CUSTOMER))
const canDeleteCustomer = computed<boolean>(() => hasAbility(ABILITIES.DELETE_CUSTOMER))
const canViewInvoice = computed<boolean>(() => hasAbility(ABILITIES.VIEW_INVOICE))
const canCreateInvoice = computed<boolean>(() => hasAbility(ABILITIES.CREATE_INVOICE))
const canEditInvoice = computed<boolean>(() => hasAbility(ABILITIES.EDIT_INVOICE))
const canDeleteInvoice = computed<boolean>(() => hasAbility(ABILITIES.DELETE_INVOICE))
const canViewEstimate = computed<boolean>(() => hasAbility(ABILITIES.VIEW_ESTIMATE))
const canCreateEstimate = computed<boolean>(() => hasAbility(ABILITIES.CREATE_ESTIMATE))
const canEditEstimate = computed<boolean>(() => hasAbility(ABILITIES.EDIT_ESTIMATE))
const canDeleteEstimate = computed<boolean>(() => hasAbility(ABILITIES.DELETE_ESTIMATE))
const canViewPayment = computed<boolean>(() => hasAbility(ABILITIES.VIEW_PAYMENT))
const canCreatePayment = computed<boolean>(() => hasAbility(ABILITIES.CREATE_PAYMENT))
const canEditPayment = computed<boolean>(() => hasAbility(ABILITIES.EDIT_PAYMENT))
const canDeletePayment = computed<boolean>(() => hasAbility(ABILITIES.DELETE_PAYMENT))
const canViewExpense = computed<boolean>(() => hasAbility(ABILITIES.VIEW_EXPENSE))
const canCreateExpense = computed<boolean>(() => hasAbility(ABILITIES.CREATE_EXPENSE))
const canEditExpense = computed<boolean>(() => hasAbility(ABILITIES.EDIT_EXPENSE))
const canDeleteExpense = computed<boolean>(() => hasAbility(ABILITIES.DELETE_EXPENSE))
const canViewDashboard = computed<boolean>(() => hasAbility(ABILITIES.DASHBOARD))
const canViewFinancialReport = computed<boolean>(() => hasAbility(ABILITIES.VIEW_FINANCIAL_REPORT))
return {
currentAbilities,
isOwner,
isSuperAdmin,
setAbilities,
setOwner,
setSuperAdmin,
hasAbility,
hasAllAbilities,
canViewCustomer,
canCreateCustomer,
canEditCustomer,
canDeleteCustomer,
canViewInvoice,
canCreateInvoice,
canEditInvoice,
canDeleteInvoice,
canViewEstimate,
canCreateEstimate,
canEditEstimate,
canDeleteEstimate,
canViewPayment,
canCreatePayment,
canEditPayment,
canDeletePayment,
canViewExpense,
canCreateExpense,
canEditExpense,
canDeleteExpense,
canViewDashboard,
canViewFinancialReport,
}
}