UNPKG

@devwizard/laravel-react-permissions

Version:

🔐 Modern, Laravel-inspired permissions system for React/Inertia.js with advanced pattern matching, boolean expressions, and zero dependencies. Features wildcard patterns, custom permissions, and full TypeScript support.

184 lines (182 loc) 7.48 kB
import { usePage } from '@inertiajs/react'; import { jsx, Fragment } from 'react/jsx-runtime'; var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); function usePermissions(permissions) { const { auth } = usePage().props; const userPermissions = permissions !== void 0 ? permissions : auth?.user?.permissions || []; const hasPermission = /* @__PURE__ */ __name((permission) => { if (permission.trim() === "true") return true; if (permission.trim() === "false") return false; if (permission.includes("*") || permission.includes("?") || permission.includes("||") || permission.includes("&&") || permission.includes("|") || permission.includes("&")) { return hasPermissionPattern(permission); } return userPermissions.includes(permission); }, "hasPermission"); const hasAnyPermission = /* @__PURE__ */ __name((permissions2) => { return permissions2.some((permission) => userPermissions.includes(permission)); }, "hasAnyPermission"); const hasAllPermissions = /* @__PURE__ */ __name((permissions2) => { return permissions2.every( (permission) => userPermissions.includes(permission) ); }, "hasAllPermissions"); const checkSimplePermissionPattern = /* @__PURE__ */ __name((pattern) => { if (pattern.trim() === "true") return true; if (pattern.trim() === "false") return false; if (pattern.trim() === "*") return true; let regexPattern = pattern.replace(/\./g, "\\.").replace(/\*/g, ".*").replace(/\?/g, "."); regexPattern = `^${regexPattern}$`; const regex = new RegExp(regexPattern); return userPermissions.some((permission) => regex.test(permission)); }, "checkSimplePermissionPattern"); const evaluatePermissionExpression = /* @__PURE__ */ __name((expression) => { if (expression.trim() === "true") return true; if (expression.trim() === "false") return false; let jsExpression = expression; jsExpression = jsExpression.replace(/\|\|/g, " DOUBLE_PIPE ").replace(/&&/g, " DOUBLE_AMP "); jsExpression = jsExpression.replace(/\|/g, " || ").replace(/&/g, " && "); jsExpression = jsExpression.replace(/DOUBLE_PIPE/g, " || ").replace(/DOUBLE_AMP/g, " && "); jsExpression = jsExpression.replace(/\s+/g, " ").trim(); const permissionRegex = /(?:\*|\?|[a-zA-Z_][a-zA-Z0-9_.*?-]*(?:\.[a-zA-Z0-9_.*?-]*)*|true|false)(?![|&])/g; const permissions2 = jsExpression.match(permissionRegex) || []; let evaluatedExpression = jsExpression; for (const permission of permissions2) { if (permission === "true" || permission === "false") continue; const hasPermissionResult = checkSimplePermissionPattern(permission); if (permission === "*" || permission === "?") { const wildcardRegex = new RegExp( `\\${permission}(?![a-zA-Z0-9_.])`, "g" ); evaluatedExpression = evaluatedExpression.replace( wildcardRegex, hasPermissionResult.toString() ); } else { const escapedPermission = permission.replace( /[.*+?^${}()|[\]\\]/g, "\\$&" ); const permissionRegex2 = new RegExp(`\\b${escapedPermission}\\b`, "g"); evaluatedExpression = evaluatedExpression.replace( permissionRegex2, hasPermissionResult.toString() ); } } try { return Function(`"use strict"; return (${evaluatedExpression})`)(); } catch (error) { console.warn("Invalid permission expression:", expression, error); return false; } }, "evaluatePermissionExpression"); const hasPermissionPattern = /* @__PURE__ */ __name((pattern) => { if (pattern.includes("||") || pattern.includes("&&") || pattern.includes("|") || pattern.includes("&")) { return evaluatePermissionExpression(pattern); } return checkSimplePermissionPattern(pattern); }, "hasPermissionPattern"); const hasAnyPattern = /* @__PURE__ */ __name((patterns) => { return patterns.some((pattern) => hasPermissionPattern(pattern)); }, "hasAnyPattern"); const hasAllPatterns = /* @__PURE__ */ __name((patterns) => { return patterns.every((pattern) => hasPermissionPattern(pattern)); }, "hasAllPatterns"); const getMatchingPermissions = /* @__PURE__ */ __name((pattern) => { let regexPattern = pattern.replace(/\./g, "\\.").replace(/\*/g, ".*").replace(/\?/g, "."); regexPattern = `^${regexPattern}$`; const regex = new RegExp(regexPattern); return userPermissions.filter((permission) => regex.test(permission)); }, "getMatchingPermissions"); const checkExpression = /* @__PURE__ */ __name((expression) => { return evaluatePermissionExpression(expression); }, "checkExpression"); const isValidExpression = /* @__PURE__ */ __name((expression) => { try { let testExpression = expression.replace(/\|(?!\|)/g, "||").replace(/&(?!&)/g, "&&"); testExpression = testExpression.replace(/\|\|\|/g, "||").replace(/&&&/g, "&&"); testExpression = testExpression.replace( /[a-zA-Z_][a-zA-Z0-9_.*?]*(?:\.[a-zA-Z0-9_.*?]*)*(?![|&])/g, "true" ); Function(`"use strict"; return (${testExpression})`); return true; } catch { return false; } }, "isValidExpression"); return { userPermissions, hasPermission, hasAnyPermission, hasAllPermissions, hasPermissionPattern, hasAnyPattern, hasAllPatterns, getMatchingPermissions, checkExpression, isValidExpression, isAuthenticated: !!auth?.user }; } __name(usePermissions, "usePermissions"); function Can({ permission, expression, anyPermissions, allPermissions, pattern, anyPatterns, allPatterns, permissions, children, fallback = null, requireAuth = true }) { const { hasPermission, hasAnyPermission, hasAllPermissions, hasPermissionPattern, hasAnyPattern, hasAllPatterns, checkExpression, isAuthenticated } = usePermissions(permissions); if (requireAuth && !isAuthenticated) { return /* @__PURE__ */ jsx(Fragment, { children: fallback }); } let hasAccess = false; if (expression) { hasAccess = checkExpression(expression); } else if (permission) { hasAccess = hasPermission(permission); } else if (anyPermissions && anyPermissions.length > 0) { hasAccess = hasAnyPermission(anyPermissions); } else if (allPermissions) { hasAccess = hasAllPermissions(allPermissions); } else if (anyPatterns && anyPatterns.length > 0) { hasAccess = hasAnyPattern(anyPatterns); } else if (allPatterns && allPatterns.length > 0) { hasAccess = hasAllPatterns(allPatterns); } else if (pattern) { hasAccess = hasPermissionPattern(pattern); } else if (!requireAuth) { hasAccess = true; } return hasAccess ? /* @__PURE__ */ jsx(Fragment, { children }) : /* @__PURE__ */ jsx(Fragment, { children: fallback }); } __name(Can, "Can"); function withPermission(Component, options) { const WrappedComponent = /* @__PURE__ */ __name((props) => { return /* @__PURE__ */ jsx(Can, { ...options, children: /* @__PURE__ */ jsx(Component, { ...props }) }); }, "WrappedComponent"); WrappedComponent.displayName = `withPermission(${Component.displayName || Component.name})`; return WrappedComponent; } __name(withPermission, "withPermission"); export { Can, usePermissions, withPermission }; //# sourceMappingURL=index.js.map //# sourceMappingURL=index.js.map