265 lines
7.4 KiB
Markdown
265 lines
7.4 KiB
Markdown
# WordPress-Style Permission System - Quick Reference
|
|
|
|
## ✅ What Was Implemented
|
|
|
|
The CGW Product Finder now has a complete WordPress-style permission system with:
|
|
|
|
1. **Permission Checking Functions** (Backend - Python)
|
|
- `can_user(permission, location=None)` - Check single permission
|
|
- `user_has_any_permission(permissions, location=None)` - Check if user has ANY permission
|
|
- `user_has_all_permissions(permissions, location=None)` - Check if user has ALL permissions
|
|
- `get_user_permissions(location=None)` - Get all user permissions
|
|
- `@permission_required(permission, location=None)` - Route decorator for permission protection
|
|
|
|
2. **Permission Check Endpoints** (Frontend - API)
|
|
- `POST /api/check-permission` - Check if user has specific permission
|
|
- `GET /api/user-permissions` - Get all user permissions
|
|
|
|
3. **Access Denial**
|
|
- Beautiful access denied page at `templates/access_denied.html`
|
|
- Shows required permission and helpful navigation
|
|
|
|
4. **Protected Routes**
|
|
- `/users` - User management page (requires `manage_users`)
|
|
- `/api/users` (GET, POST, PATCH, DELETE) - All user management endpoints protected
|
|
|
|
5. **User Data Structure**
|
|
- Global permissions: `user.permissions`
|
|
- Location-specific permissions: `user.locationSettings[LOCATION].permissions`
|
|
|
|
## 🚀 Quick Start Usage
|
|
|
|
### Backend (Python)
|
|
|
|
```python
|
|
# Check permission
|
|
if can_user('create_quotes'):
|
|
# User can create quotes
|
|
pass
|
|
|
|
# Protect a route
|
|
@app.route('/admin/reports')
|
|
@login_required
|
|
@permission_required('view_reports')
|
|
def admin_reports():
|
|
return render_template('reports.html')
|
|
|
|
# Check at specific location
|
|
if can_user('manage_inventory', location='LINDS'):
|
|
# User can manage inventory at Lindsborg
|
|
pass
|
|
```
|
|
|
|
### Frontend (JavaScript)
|
|
|
|
```javascript
|
|
// Check single permission
|
|
const response = await fetch('/api/check-permission', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ permission: 'create_quotes' })
|
|
});
|
|
const data = await response.json();
|
|
if (data.hasPermission) {
|
|
// Show create button
|
|
}
|
|
|
|
// Get all permissions
|
|
const response = await fetch('/api/user-permissions');
|
|
const data = await response.json();
|
|
console.log(data.permissions); // { manage_users: true, create_quotes: true, ... }
|
|
```
|
|
|
|
## 📁 Files Modified/Created
|
|
|
|
### Created:
|
|
- `app/templates/access_denied.html` - Access denial page
|
|
- `app/PERMISSIONS_SYSTEM.md` - Comprehensive documentation
|
|
|
|
### Modified:
|
|
- `app/app.py` - Added permission checking functions and protected routes
|
|
- `app/data/users.json` - Added permissions to existing users
|
|
- `app/data/example_user_structure.json` - Updated with permission examples
|
|
|
|
## 👥 Current Users & Permissions
|
|
|
|
### Master (Admin)
|
|
- **Password**: Master
|
|
- **Location**: KC (access to all locations)
|
|
- **Permissions**: Full access
|
|
- manage_users ✅
|
|
- view_reports ✅
|
|
- create_quotes ✅
|
|
- approve_quotes ✅
|
|
- manage_products ✅
|
|
- manage_inventory ✅
|
|
|
|
### Darlene (Standard User)
|
|
- **Password**: Darlene
|
|
- **Location**: IOLA (access to LINDS, IOLA, KC)
|
|
- **Permissions**: Limited access
|
|
- manage_users ✅
|
|
- view_reports ✅
|
|
- create_quotes ✅
|
|
- approve_quotes ❌
|
|
- manage_products ❌
|
|
- manage_inventory ❌
|
|
|
|
## 🔒 Permission Hierarchy
|
|
|
|
```
|
|
Check Order:
|
|
1. Is user logged in? → If no: return False
|
|
2. Is user active? → If no: return False
|
|
3. Check global permissions (user.permissions) → If found: return value
|
|
4. Check location-specific permissions → If found: return value
|
|
5. Default: return False
|
|
```
|
|
|
|
## 🎯 Common Permission Names
|
|
|
|
Recommended permissions for your system:
|
|
|
|
**User Management:**
|
|
- `manage_users` - Create, edit, delete users (already implemented)
|
|
- `view_users` - View user list
|
|
- `reset_passwords` - Reset passwords
|
|
|
|
**Products & Inventory:**
|
|
- `manage_products` - Add/edit/delete products
|
|
- `view_products` - View product catalog
|
|
- `manage_inventory` - Adjust inventory
|
|
- `view_inventory` - View inventory
|
|
|
|
**Quotes & Orders:**
|
|
- `create_quotes` - Create quotes
|
|
- `view_quotes` - View quotes
|
|
- `approve_quotes` - Approve/reject quotes
|
|
- `edit_quotes` - Edit quotes
|
|
|
|
**Reports:**
|
|
- `view_reports` - Access reports
|
|
- `export_data` - Export data
|
|
- `view_analytics` - View analytics
|
|
|
|
## 🧪 Testing the System
|
|
|
|
### Test 1: User Management Access
|
|
```bash
|
|
1. Start Flask server: python app/app.py
|
|
2. Login as Master (password: Master)
|
|
3. Navigate to /users
|
|
4. Should see user management interface ✅
|
|
```
|
|
|
|
### Test 2: Permission Denied
|
|
```bash
|
|
1. Create a new user without manage_users permission
|
|
2. Login as that user
|
|
3. Navigate to /users
|
|
4. Should see "Access Denied" page ✅
|
|
```
|
|
|
|
### Test 3: API Permission Check
|
|
```bash
|
|
# In browser console after login:
|
|
const response = await fetch('/api/check-permission', {
|
|
method: 'POST',
|
|
headers: {'Content-Type': 'application/json'},
|
|
body: JSON.stringify({permission: 'manage_users'})
|
|
});
|
|
const data = await response.json();
|
|
console.log(data.hasPermission); // Should be true for Master
|
|
```
|
|
|
|
### Test 4: Get All Permissions
|
|
```bash
|
|
# In browser console after login:
|
|
const response = await fetch('/api/user-permissions');
|
|
const data = await response.json();
|
|
console.log(data.permissions); // Should show all user's permissions
|
|
```
|
|
|
|
## 📝 Next Steps
|
|
|
|
To add permissions to new features:
|
|
|
|
1. **Define Permission Name**
|
|
```python
|
|
# Choose a descriptive name like 'create_quotes'
|
|
```
|
|
|
|
2. **Protect Backend Route**
|
|
```python
|
|
@app.route('/quotes/new')
|
|
@login_required
|
|
@permission_required('create_quotes')
|
|
def new_quote():
|
|
return render_template('new_quote.html')
|
|
```
|
|
|
|
3. **Check in Code**
|
|
```python
|
|
if can_user('create_quotes'):
|
|
# Allow quote creation
|
|
```
|
|
|
|
4. **Hide/Show Frontend Elements**
|
|
```javascript
|
|
const perms = await fetch('/api/user-permissions').then(r => r.json());
|
|
if (perms.permissions.create_quotes) {
|
|
document.getElementById('createBtn').style.display = 'block';
|
|
}
|
|
```
|
|
|
|
5. **Add to User Data**
|
|
```json
|
|
{
|
|
"username": "user",
|
|
"permissions": {
|
|
"create_quotes": true
|
|
}
|
|
}
|
|
```
|
|
|
|
## 🛠️ Troubleshooting
|
|
|
|
**Access Denied even with permission:**
|
|
- Check spelling of permission name (case-sensitive)
|
|
- Verify user is active in users.json
|
|
- Clear browser cookies and re-login
|
|
- Check server logs for errors
|
|
|
|
**Permission check returns False:**
|
|
- Ensure user is logged in
|
|
- Verify permission exists in users.json
|
|
- Check if using correct location context
|
|
- Confirm session is valid
|
|
|
|
**Frontend shows button but backend denies:**
|
|
- This is correct! Frontend checks are for UX only
|
|
- Backend always enforces permissions
|
|
- Never trust client-side permission checks
|
|
|
|
## 📚 Full Documentation
|
|
|
|
See `app/PERMISSIONS_SYSTEM.md` for complete documentation including:
|
|
- Detailed examples
|
|
- Best practices
|
|
- Security notes
|
|
- Migration guide
|
|
- Advanced usage patterns
|
|
|
|
## 🎉 Summary
|
|
|
|
You now have a fully functional WordPress-style permission system that allows:
|
|
- ✅ Fine-grained access control
|
|
- ✅ Global and location-specific permissions
|
|
- ✅ Easy permission checks in code
|
|
- ✅ Protected routes with decorators
|
|
- ✅ Frontend permission checking
|
|
- ✅ Beautiful access denied pages
|
|
- ✅ Flexible permission inheritance
|
|
|
|
The system is secure, scalable, and follows WordPress best practices!
|