Cursor rule
.cursor/rules/role-based-access-patterns.mdcRole-based access control (RBAC) patterns and implementations for POS System
Cursor rules
Quality
58/100
Scores the file, not the repository.Length
746 words
23 headings · 12 code blocksRepository
118
— · pushed 339 days agoLast changed
3 days ago
First indexed 3 days ago.123456# Role-Based Access Control (RBAC) Patterns78## Role Definitions910### Available Roles11```typescript12type UserRole = 'admin' | 'manager' | 'server' | 'counter' | 'kitchen'13```1415### Role Capabilities16- **admin**: Full system access, can switch to any interface17- **manager**: Business operations, reports, staff oversight18- **server**: Dine-in order creation only19- **counter**: All order types + payment processing20- **kitchen**: Order preparation and status updates2122## Frontend Role Routing2324### Main Router Pattern25```typescript26// RoleBasedLayout.tsx27export function RoleBasedLayout({ user }: { user: User }) {28 // Admin gets AdminLayout with all interfaces29 if (user.role === 'admin') {30 return <AdminLayout user={user} />31 }3233 // Other roles get specific interfaces34 switch (user.role) {35 case 'server': return <ServerInterface />36 case 'counter': return <CounterInterface />37 case 'kitchen': return <KitchenLayout user={user} />38 default: return <POSLayout user={user} />39 }40}41```4243### Navigation Access Control44```typescript45// AdminLayout.tsx - Admin can access all interfaces46const adminSections = [47 { id: 'dashboard', label: 'Dashboard' },48 { id: 'pos', label: 'General POS' }, // Full POS access49 { id: 'server', label: 'Server Interface' }, // Server view50 { id: 'counter', label: 'Counter/Checkout' }, // Counter view51 { id: 'kitchen', label: 'Kitchen Display' } // Kitchen view52 // + admin-only sections53]54```5556## Backend API Role Restrictions5758### Route Groups by Role59```go60// routes.go pattern61func setupRoutes(router *gin.Engine) {62 api := router.Group("/api/v1")6364 // Public routes65 api.POST("/auth/login", handlers.Login)6667 // Protected routes68 protected := api.Group("", middleware.RequireAuth)6970 // Admin only71 admin := protected.Group("/admin", middleware.RequireRole("admin"))72 admin.GET("/users", handlers.GetUsers)73 admin.POST("/users", handlers.CreateUser)7475 // Server only76 server := protected.Group("/server", middleware.RequireRole("server"))77 server.POST("/orders", handlers.CreateDineInOrder) // Restricted to dine_in7879 // Counter access80 counter := protected.Group("/counter", middleware.RequireRoles("counter", "admin"))81 counter.POST("/orders", handlers.CreateCounterOrder) // All order types82 counter.POST("/orders/:id/payments", handlers.ProcessPayment)83}84```8586### Role-Specific Endpoints87```typescript88// API Client role-specific methods89class APIClient {90 // Admin-only endpoints91 async getUsers(): Promise<APIResponse<User[]>> {92 return this.request({ method: 'GET', url: '/admin/users' });93 }9495 // Server-specific (dine-in only)96 async createServerOrder(order: CreateOrderRequest): Promise<APIResponse<Order>> {97 return this.request({ method: 'POST', url: '/server/orders', data: order });98 }99100 // Counter-specific (all order types + payments)101 async createCounterOrder(order: CreateOrderRequest): Promise<APIResponse<Order>> {102 return this.request({ method: 'POST', url: '/counter/orders', data: order });103 }104105 async processCounterPayment(orderId: string, payment: ProcessPaymentRequest): Promise<APIResponse<Payment>> {106 return this.request({ method: 'POST', url: `/counter/orders/${orderId}/payments`, data: payment });107 }108}109```110111## Component-Level Access Control112113### Conditional Rendering by Role114```typescript115// Show admin-only features116{user.role === 'admin' && (117 <Button onClick={() => navigate('/admin')}>118 Admin Dashboard119 </Button>120)}121122// Show based on multiple roles123{['admin', 'manager'].includes(user.role) && (124 <ReportsSection />125)}126```127128### Form Restrictions129```typescript130// ServerInterface.tsx - Only dine-in orders131const ServerInterface = () => {132 const createOrderMutation = useMutation({133 mutationFn: (order: CreateOrderRequest) => {134 // Force dine_in type for servers135 return apiClient.createServerOrder({136 ...order,137 order_type: 'dine_in'138 })139 }140 })141142 // Hide takeout/delivery options in UI143 const availableOrderTypes = ['dine_in'] // Only option for servers144}145```146147## Database Role Validation148149### User Schema150```sql151-- users table with role enum152CREATE TYPE user_role AS ENUM ('admin', 'manager', 'server', 'counter', 'kitchen');153154ALTER TABLE users ADD COLUMN role user_role NOT NULL DEFAULT 'server';155```156157### Sample Role Data158```sql159-- Seed data with all roles160INSERT INTO users (username, email, password_hash, first_name, last_name, role) VALUES161('admin', 'admin@pos.com', '$2b$10$...', 'Admin', 'User', 'admin'),162('server1', 'server1@pos.com', '$2b$10$...', 'Sarah', 'Smith', 'server'),163('counter1', 'counter1@pos.com', '$2b$10$...', 'Lisa', 'Davis', 'counter'),164('kitchen1', 'kitchen@pos.com', '$2b$10$...', 'Chef', 'Williams', 'kitchen');165```166167## Authentication Flow168169### Login Process170```typescript171// login.tsx172const loginMutation = useMutation({173 mutationFn: async (credentials: LoginRequest) => {174 const response = await apiClient.login(credentials)175 return response176 },177 onSuccess: (data) => {178 if (data.success && data.data) {179 // Store user info with role180 apiClient.setAuthToken(data.data.token)181 localStorage.setItem('pos_user', JSON.stringify(data.data.user))182 router.navigate({ to: '/' })183 }184 }185})186```187188### Route Protection189```typescript190// index.tsx191function HomePage() {192 const [user, setUser] = useState<User | null>(null)193194 useEffect(() => {195 const storedUser = localStorage.getItem('pos_user')196 if (storedUser) {197 setUser(JSON.parse(storedUser))198 }199 }, [])200201 // Redirect if not authenticated202 if (!apiClient.isAuthenticated() || !user) {203 return <Navigate to="/login" />204 }205206 // Role-based routing207 return <RoleBasedLayout user={user} />208}209```210211## Security Best Practices212213### Frontend Security214- Never trust frontend role checks alone215- Always validate roles on backend216- Store minimal user data in localStorage217- Clear auth on logout218219### Backend Security220- Use middleware for role validation221- Check roles on every protected endpoint222- Log access attempts for audit223- Implement proper session management224225### Error Handling226```typescript227// Handle role access errors gracefully228onError: (error: any) => {229 if (error.status === 403) {230 alert('Access denied: Insufficient permissions')231 } else {232 alert(`Error: ${error.message}`)233 }234}235```
Also in madebyaris/poinf-of-sales
Diff this repo’s formatsOne repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| madebyaris/poinf-of-sales.cursor/rules/admin-interface-patterns.mdc · 118 | Cursor rules | stylearchsecurityapi+2 | 62/100 | 3 days ago | |
| madebyaris/poinf-of-sales.cursor/rules/api-patterns.mdc · 118 | Cursor rules | lint-formatstylesecuritydatabase+3 | 62/100 | 3 days ago | |
| madebyaris/poinf-of-sales.cursor/rules/authentication-and-security-patterns.mdc · 118 | Cursor rules | setupteststylesecurity+4 | 81/100 | 3 days ago | |
| madebyaris/poinf-of-sales.cursor/rules/backend-golang.mdc · 118 | Cursor rules | testlint-formatstylearch+5 | 69/100 | 3 days ago | |
| madebyaris/poinf-of-sales.cursor/rules/business-logic-patterns.mdc · 118 | Cursor rules | teststyledatabaseperformance+1 | 50/100 | 3 days ago | |
| madebyaris/poinf-of-sales.cursor/rules/database-patterns.mdc · 118 | Cursor rules | stylearchtypessecurity+2 | 62/100 | 3 days ago | |
| madebyaris/poinf-of-sales.cursor/rules/development-workflow.mdc · 118 | Cursor rules | setupbuildteststyle+3 | 86/100 | 3 days ago | |
| madebyaris/poinf-of-sales.cursor/rules/docker-deployment.mdc · 118 | Cursor rules | setupbuildteststyle+8 | 77/100 | 3 days ago | |
| madebyaris/poinf-of-sales.cursor/rules/frontend-react.mdc · 118 | Cursor rules | buildtestlint-formatstyle+4 | 69/100 | 3 days ago | |
| madebyaris/poinf-of-sales.cursor/rules/makefile-scripting.mdc · 118 | Cursor rules | setuplint-formatstylearch+2 | 81/100 | 3 days ago | |
| madebyaris/poinf-of-sales.cursor/rules/performance-optimization-patterns.mdc · 118 | Cursor rules | buildteststyledatabase+3 | 66/100 | 3 days ago | |
| madebyaris/poinf-of-sales.cursor/rules/project-architecture.mdc · 118 | Cursor rules | setupteststylearch+6 | 78/100 | 3 days ago | |
| madebyaris/poinf-of-sales.cursor/rules/react-native-mobile-patterns.mdc · 118 | Cursor rules | buildstylearchui+2 | 74/100 | 3 days ago | |
| madebyaris/poinf-of-sales.cursor/rules/tech-debt-prevention.mdc · 118 | Cursor rules | styletesting-strategyui | 50/100 | 3 days ago | |
| madebyaris/poinf-of-sales.cursor/rules/testing-patterns.mdc · 118 | Cursor rules | setupteststylearch+4 | 74/100 | 3 days ago | |
| madebyaris/poinf-of-sales.cursor/rules/user-journey-optimization.mdc · 118 | Cursor rules | styleperformanceagent-behaviour | 50/100 | 3 days ago |
Diff against .cursor/rules/admin-interface-patterns.mdc Diff against .cursor/rules/api-patterns.mdc Diff against .cursor/rules/authentication-and-security-patterns.mdc Diff against .cursor/rules/backend-golang.mdc Diff against .cursor/rules/business-logic-patterns.mdc Diff against .cursor/rules/database-patterns.mdc Diff against .cursor/rules/development-workflow.mdc Diff against .cursor/rules/docker-deployment.mdc Diff against .cursor/rules/frontend-react.mdc Diff against .cursor/rules/makefile-scripting.mdc Diff against .cursor/rules/performance-optimization-patterns.mdc Diff against .cursor/rules/project-architecture.mdc Diff against .cursor/rules/react-native-mobile-patterns.mdc Diff against .cursor/rules/tech-debt-prevention.mdc Diff against .cursor/rules/testing-patterns.mdc Diff against .cursor/rules/user-journey-optimization.mdc
Similar configs
Same format, overlapping stack, ranked by quality.
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| hiromaily/go-crypto-wallet.cursor/rules/typescript.mdc · 126 | Cursor rules | setupbuildtestlint-format+6 | 100/100 | 3 days ago | |
| TechSquidTV/Hermes.cursor/rules/10-hermes-api.mdc · 45 | Cursor rules | testlint-formatstylearch+5 | 100/100 | 3 days ago | |
| markstev/mark-starter.cursor/rules/frontend.mdc · 0 | Cursor rules | setuptestlint-formatstyle+6 | 99/100 | 3 days ago | |
| Allymahmoud/case-intake-platform.cursor/rules/frontend.mdc · 0 | Cursor rules | setuptestlint-formatstyle+7 | 99/100 | 3 days ago | |
| dodgecfr/combatfilms-webapp.cursor/rules/frontend.mdc · 0 | Cursor rules | setuptestlint-formatstyle+7 | 99/100 | 3 days ago | |
| deifos/clipmira-subtitles.cursor/rules/frontend.mdc · 1 | Cursor rules | setuptestlint-formatstyle+7 | 99/100 | 3 days ago | |
| langflow-ai/langflow.cursor/rules/docs_development.mdc · 153k | Cursor rules | setupbuildtestlint-format+7 | 97/100 | 3 days ago | |
| TechSquidTV/Hermes.cursor/rules/20-hermes-api-tests.mdc · 45 | Cursor rules | teststyletesting-strategysecurity+3 | 97/100 | 3 days ago |
