Skip to content

Implement three-layer permission system with URY roles and capabilities#96

Draft
esafwan wants to merge 3 commits intodevelopfrom
claude/implement-permissions-roles-q7ggj
Draft

Implement three-layer permission system with URY roles and capabilities#96
esafwan wants to merge 3 commits intodevelopfrom
claude/implement-permissions-roles-q7ggj

Conversation

@esafwan
Copy link
Copy Markdown
Contributor

@esafwan esafwan commented Mar 23, 2026

Summary

Introduces a comprehensive three-layer permission system for URY consisting of:

  1. Capability Layer — Fine-grained capabilities (e.g., users.create, orders.view_all) checked throughout the application
  2. URY Role Layer — Named roles (e.g., URY Admin, URY Manager, URY Cashier) that own sets of capabilities
  3. Frappe Role Layer — Backing Frappe roles for DocType-level enforcement and desk access control

Key Changes

Backend (Python/Frappe)

  • ury/ury/permissions.py — Core permission engine with:

    • Capability catalogue (50+ fine-grained capabilities)
    • URY role definitions with default capability sets
    • Role-to-Frappe role mapping for desk access control
    • has_capability() and get_user_capabilities() functions for runtime checks
  • ury/ury/api/permissions_api.py — Whitelisted REST endpoints:

    • User management: get_users(), invite_user(), update_user_role(), set_user_enabled()
    • Role management: get_ury_roles(), create_ury_role(), update_ury_role()
    • All endpoints guarded with _require(capability) checks
  • New DocTypes:

    • URY Role — Stores role definitions with capability assignments
    • URY User Role — Links users to URY roles with enable/disable toggle
    • URY Role Permission — Child table for capability assignments
  • ury/install.py — Idempotent role seeding:

    • Creates Frappe backing roles for all URY roles
    • Seeds system URY roles with default capability sets
    • Assigns Administrator the URY Admin role
    • Migrates existing users to appropriate roles
    • Runs on both after_install and after_migrate hooks

Frontend (React/TypeScript)

  • pos/src/lib/permissions-api.ts — TypeScript API client:

    • Type definitions for MeResponse, URYUser, URYRole, URYRoleCapability
    • Async functions wrapping backend endpoints with error handling
  • pos/src/contexts/PermissionsContext.tsx — React context provider:

    • Exposes usePermissions() hook for capability checks
    • hasCapability(capability) method for conditional rendering/logic
    • Auto-refreshes on mount
  • pos/src/pages/admin/UsersPage.tsx — User management UI:

    • List all users with search and status filtering
    • Invite new users with role assignment
    • Change user roles via dropdown
    • Enable/disable users with toggle
    • Role-based color coding for visual distinction
    • Permission-gated actions (only visible to users with users.manage or users.create)

Notable Implementation Details

  • Capability-first design: All API endpoints check capabilities, not just Frappe roles
  • Desk access control: Roles marked with desk_access=1 get Frappe desk access; others are frontend-only
  • Idempotent seeding: Role creation is safe to run on every migrate without duplicates
  • Frappe role sync: URYUserRole.on_update() automatically syncs Frappe roles when URY role changes
  • Cache busting: Role changes invalidate user capability caches for immediate effect
  • 15 system roles pre-configured with role-specific capability sets (Admin, Ops Admin, Manager, Director, Purchase Manager, Sales Manager, Accountant, Analyst, Captain, Servicer, Cashier, Chef, Store Manager, Store Admin, Store Accountant)

https://claude.ai/code/session_01TZ1yuzhjsj7276Qm3nZESS

claude and others added 3 commits March 23, 2026 17:57
Adds a three-layer permission system for URY:
1. Capability layer — 24 fine-grained capabilities across orders,
   payments, kitchen, dispatch, reports, settings, users, and roles
2. URY Role layer — 13 named roles (Admin, Ops Admin, Manager,
   Director, Purchase/Sales Manager, Accountant, Analyst, Captain,
   Servicer, Cashier, Chef, Store Manager/Admin/Accountant) each
   owning a set of capabilities
3. Frappe Role layer — backing Frappe roles for DocType-level
   permission enforcement with desk/non-desk access control

Backend:
- URY Role, URY User Role, URY Role Permission doctypes
- Capability engine with caching (ury/ury/permissions.py)
- Whitelisted API endpoints for user/role CRUD (permissions_api.py)
- App permission check via URY User Role
- Install/migrate hooks for idempotent role seeding
- Migration patch for existing URY Manager/Captain/Cashier users
- Frappe role fixtures for all 14 backing roles

Frontend:
- React PermissionsContext for capability-based UI gating
- TypeScript API client for all permissions endpoints
- User management page with invite, role change, enable/disable

https://claude.ai/code/session_01TZ1yuzhjsj7276Qm3nZESS
- Add /settings route with sidebar navigation
- Add ProtectedRoute component for capability-based access control
- Add SettingsLayout component with Users and Roles navigation
- Add RolesPage for read-only role viewing with capability grouping
- Update Header with Settings link in user dropdown (gated by capability)
- Wrap App with PermissionsProvider
- Add URY Role and URY User Role to fixtures export
- Add optional chaining to prevent crash when capabilities is undefined
- This can happen when the API returns without capabilities field
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants