# Dynamic Permission System Documentation

## Overview

This system uses access names instead of user IDs to manage permissions. After the middleware verifies the user token, it calls an API to fetch the user's access permissions, which are then used to control both route access and sidebar visibility.

## Access Types

There are 4 access types:

1. **Store keeper** - Access to:
   - Category
   - Products
   - Vendors
   - QR Generator
   - Add Inventory

2. **PO View** - Access to:
   - PO Panel (Purchase Orders)

3. **Accounts** - Access to:
   - All Payments
   - PO Pay
   - History
   - PO Panel (Purchase Orders)

4. **User** - Access to:
   - Request Item
   - Approvals
   - Store Keeper
   - Purchase Officer Request
   - Quotation Approval

## API Endpoint Required

You need to create an API endpoint that returns the user's access permissions.

### Endpoint
```
POST /api/user-access
```

### Request Body
```json
{
  "user_id": "123"
}
```

### Response Format (Option 1 - Recommended)
```json
{
  "success": true,
  "data": {
    "access": ["Store keeper", "User"]
  }
}
```

### Response Format (Option 2)
```json
{
  "access": ["Store keeper", "User"]
}
```

### Response Format (Option 3)
```json
["Store keeper", "User"]
```

## File Structure

- `accessMapping.js` - Maps routes and sidebar items to access names
- `fetchUserAccess.js` - Fetches user access from API with caching
- `checkRouteAccess.js` - Checks if user has route access
- `hasSidebarAccess.js` - Checks if user has sidebar item access
- `sidebarPermissions.js` - Sidebar structure with access mapping
- `routePermissions.js` - Route structure with access mapping
- `useUserAccess.js` - React hook to fetch user access in components

## How It Works

### 1. Middleware Flow

```javascript
// middleware.js
1. Verify JWT token
2. Extract user_id from token
3. Call getUserAccess(userId) to fetch access names from API
4. Use hasRouteAccess(userAccess, pathname) to check route permission
5. Allow or deny access based on result
```

### 2. Sidebar Flow

```javascript
// Sidebar.js
1. Component uses useUserAccess() hook
2. Hook fetches user access from API
3. Sidebar items are filtered using hasSidebarAccess(userAccess, item.access)
4. Only accessible items are displayed
```

### 3. Route Access Mapping

Routes are mapped to access names in `accessMapping.js`:

```javascript
export const ROUTE_ACCESS_MAPPING = {
  "/inventory/purchase": [ACCESS_NAMES.USER],
  "/inventory/category": [ACCESS_NAMES.STORE_KEEPER],
  "/inventory/purchase-orders": [ACCESS_NAMES.PO_VIEW, ACCESS_NAMES.ACCOUNTS],
  // ...
};
```

## Adding New Routes

1. Add route to `ROUTE_ACCESS_MAPPING` in `accessMapping.js`
2. Add route to `SIDEBAR_ACCESS_MAPPING` if it should appear in sidebar
3. Add sidebar item to `SIDEBAR_SECTIONS` in `sidebarPermissions.js`

## Example: Backend API Implementation

### Node.js/Express Example

```javascript
// routes/user-access.js
router.post('/user-access', async (req, res) => {
  const { user_id } = req.body;
  
  try {
    // Fetch user access from database
    const user = await User.findById(user_id);
    
    // Get access names based on user role or permissions
    const access = [];
    
    if (user.role === 'store_keeper') {
      access.push('Store keeper');
    }
    if (user.can_view_po) {
      access.push('PO View');
    }
    if (user.is_accountant) {
      access.push('Accounts');
    }
    if (user.is_user) {
      access.push('User');
    }
    
    res.json({
      success: true,
      data: {
        access: access
      }
    });
  } catch (error) {
    res.status(500).json({
      success: false,
      message: 'Failed to fetch user access'
    });
  }
});
```

### SQL Example

```sql
-- Example table structure
CREATE TABLE user_access (
  user_id INT,
  access_name VARCHAR(50),
  PRIMARY KEY (user_id, access_name)
);

-- Insert access
INSERT INTO user_access (user_id, access_name) VALUES
  (123, 'Store keeper'),
  (123, 'User');

-- Query access
SELECT access_name FROM user_access WHERE user_id = 123;
```

## Caching

User access is cached for 5 minutes to reduce API calls. To clear cache:

```javascript
import { clearAccessCache } from '@/app/utils/fetchUserAccess';

// Clear specific user cache
clearAccessCache(userId);

// Clear all cache
clearAccessCache();
```

## Testing

1. Ensure your API endpoint returns access in the correct format
2. Test with different access combinations:
   - User with only "User" access
   - User with "Store keeper" and "User" access
   - User with "Accounts" and "PO View" access
3. Verify routes are blocked/allowed correctly
4. Verify sidebar items show/hide correctly

## Troubleshooting

### Access not working
- Check API endpoint is returning correct format
- Check access names match exactly (case-sensitive)
- Check browser console for errors
- Check middleware logs for access checks

### Sidebar not updating
- Clear access cache
- Check useUserAccess hook is fetching correctly
- Verify user object is in context

### Route access issues
- Verify route is in ROUTE_ACCESS_MAPPING
- Check middleware logs
- Verify user has correct access names

