Django_Basic_Manufacturing_3/authz_plan.md
2025-08-22 17:05:22 +07:00

423 lines
11 KiB
Markdown

# Authentication and Authorization Plan for Django Manufacturing App
## Overview
This document outlines the authentication and authorization system for the manufacturing application, including user roles, permissions, and access control mechanisms.
## Authentication System
### 1. Custom User Model
```python
# accounts/models.py
from django.contrib.auth.models import AbstractUser
from django.db import models
class User(AbstractUser):
phone = models.CharField(max_length=20, blank=True)
department = models.CharField(max_length=100, blank=True)
position = models.CharField(max_length=100, blank=True)
is_active = models.BooleanField(default=True)
date_joined = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.username
@property
def full_name(self):
return f"{self.first_name} {self.last_name}".strip() or self.username
def has_module_access(self, module_name):
"""Check if user has access to a specific module"""
if self.is_superuser:
return True
return self.groups.filter(permissions__codename__icontains=module_name).exists()
```
### 2. Authentication Views
```python
# accounts/views.py
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from django.shortcuts import render, redirect
from django.contrib import messages
from .forms import LoginForm
def login_view(request):
if request.method == 'POST':
form = LoginForm(request.POST)
if form.is_valid():
username = form.cleaned_data['username']
password = form.cleaned_data['password']
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
next_url = request.GET.get('next', 'dashboard:home')
return redirect(next_url)
else:
messages.error(request, 'Invalid username or password.')
else:
form = LoginForm()
return render(request, 'accounts/login.html', {'form': form})
@login_required
def logout_view(request):
logout(request)
messages.info(request, 'You have been logged out.')
return redirect('accounts:login')
```
## Authorization System
### 3. Permission Structure
The application will use Django's built-in permission system with custom permissions for each module:
#### Core Permissions:
- `view_module`: Can view module data
- `add_module`: Can create new records
- `change_module`: Can edit existing records
- `delete_module`: Can delete records
#### Module-specific Permissions:
**User Management:**
- `view_user`
- `add_user`
- `change_user`
- `delete_user`
- `view_role`
- `add_role`
- `change_role`
- `delete_role`
**Inventory Management:**
- `view_product`
- `add_product`
- `change_product`
- `delete_product`
- `view_inventory`
- `change_inventory`
- `view_stockmovement`
- `add_stockmovement`
**Purchasing:**
- `view_supplier`
- `add_supplier`
- `change_supplier`
- `delete_supplier`
- `view_purchaseorder`
- `add_purchaseorder`
- `change_purchaseorder`
- `delete_purchaseorder`
- `view_goodsreceipt`
- `add_goodsreceipt`
**Sales:**
- `view_customer`
- `add_customer`
- `change_customer`
- `delete_customer`
- `view_salesorder`
- `add_salesorder`
- `change_salesorder`
- `delete_salesorder`
- `view_delivery`
- `add_delivery`
**Manufacturing:**
- `view_billofmaterial`
- `add_billofmaterial`
- `change_billofmaterial`
- `delete_billofmaterial`
- `view_manufacturingorder`
- `add_manufacturingorder`
- `change_manufacturingorder`
- `delete_manufacturingorder`
**Database Management:**
- `view_databasebackup`
- `add_databasebackup`
- `change_databasebackup`
- `delete_databasebackup`
- `can_backup_database`
- `can_restore_database`
- `can_initialize_database`
**Reports:**
- `view_report`
- `generate_report`
- `export_report`
**Dashboard:**
- `view_dashboard`
- `customize_dashboard`
### 4. Role Definitions
#### Superuser
- Has all permissions by default
- Can access all modules
- Can manage users and roles
- Can perform database management operations
#### Administrator
- Can access all modules except database management
- Can manage users (except other administrators)
- Can generate and export reports
- Can customize dashboard
#### Manager
- Can view and manage data in all business modules
- Cannot delete critical records
- Can generate reports
- Limited dashboard customization
#### Supervisor
- Can view and manage data in assigned modules
- Cannot create or delete records
- Can view reports
- Basic dashboard access
#### Staff
- Limited access to specific modules
- Can view and update assigned records
- Cannot access reports or dashboard customization
### 5. Permission Assignment
#### Creating Permissions in Models
```python
# inventory/models.py
from django.db import models
class Product(models.Model):
code = models.CharField(max_length=50, unique=True)
name = models.CharField(max_length=200)
# ... other fields
class Meta:
permissions = [
("view_product", "Can view product"),
("add_product", "Can add product"),
("change_product", "Can change product"),
("delete_product", "Can delete product"),
]
```
#### Group-based Permission Management
```python
# accounts/management/commands/create_groups.py
from django.core.management.base import BaseCommand
from django.contrib.auth.models import Group, Permission
from django.contrib.contenttypes.models import ContentType
class Command(BaseCommand):
help = 'Create user groups with appropriate permissions'
def handle(self, *args, **options):
# Create groups
admin_group, created = Group.objects.get_or_create(name='Administrator')
manager_group, created = Group.objects.get_or_create(name='Manager')
supervisor_group, created = Group.objects.get_or_create(name='Supervisor')
staff_group, created = Group.objects.get_or_create(name='Staff')
# Assign permissions to Administrator group
# (Can access all modules except database management)
admin_permissions = Permission.objects.exclude(
content_type__app_label='database_management'
).exclude(
codename__in=['can_backup_database', 'can_restore_database', 'can_initialize_database']
)
admin_group.permissions.set(admin_permissions)
# Assign permissions to other groups as needed
# ...
self.stdout.write(
self.style.SUCCESS('Successfully created user groups')
)
```
### 6. Permission Checking in Views
#### Function-based Views
```python
# inventory/views.py
from django.contrib.auth.decorators import login_required, permission_required
from django.shortcuts import render
@login_required
@permission_required('inventory.view_product', raise_exception=True)
def product_list_view(request):
products = Product.objects.all()
return render(request, 'inventory/product_list.html', {'products': products})
@login_required
@permission_required('inventory.add_product', raise_exception=True)
def create_product_view(request):
# Create product logic
pass
```
#### Class-based Views
```python
# purchasing/views.py
from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin
from django.views.generic import ListView, CreateView
class PurchaseOrderListView(LoginRequiredMixin, PermissionRequiredMixin, ListView):
model = PurchaseOrder
template_name = 'purchasing/po_list.html'
context_object_name = 'purchase_orders'
permission_required = 'purchasing.view_purchaseorder'
def handle_no_permission(self):
messages.error(self.request, 'You do not have permission to view purchase orders.')
return redirect('dashboard:home')
```
### 7. Custom Permission Mixins
```python
# accounts/mixins.py
from django.contrib.auth.mixins import AccessMixin
from django.contrib import messages
from django.shortcuts import redirect
class ModuleAccessMixin(AccessMixin):
"""Verify that the current user has access to the module."""
module_name = None
def dispatch(self, request, *args, **kwargs):
if not request.user.is_authenticated:
return self.handle_no_permission()
if not request.user.has_module_access(self.module_name):
messages.error(request, f'You do not have access to the {self.module_name} module.')
return redirect('dashboard:home')
return super().dispatch(request, *args, **kwargs)
```
### 8. Template-level Permission Checking
```html
<!-- In templates, check permissions like this -->
{% if perms.inventory.add_product %}
<a href="{% url 'inventory:create_product' %}" class="btn btn-primary">
<i class="fas fa-plus"></i> Add Product
</a>
{% endif %}
<!-- Or check multiple permissions -->
{% if perms.inventory.view_product and perms.inventory.change_product %}
<!-- Show edit functionality -->
{% endif %}
```
### 9. Admin Interface Permissions
```python
# accounts/admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import User
@admin.register(User)
class CustomUserAdmin(UserAdmin):
list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff', 'is_active')
list_filter = ('is_staff', 'is_superuser', 'is_active', 'groups')
fieldsets = UserAdmin.fieldsets + (
('Additional Info', {'fields': ('phone', 'department', 'position')}),
)
add_fieldsets = UserAdmin.add_fieldsets + (
('Additional Info', {'fields': ('phone', 'department', 'position')}),
)
```
### 10. Permission Checking in Templates
```html
<!-- Check if user has specific permissions -->
{% if user.is_superuser %}
<!-- Show admin-only features -->
{% endif %}
{% if perms.inventory.view_product %}
<!-- Show inventory features -->
{% endif %}
<!-- Check multiple permissions -->
{% if perms.purchasing.view_purchaseorder and perms.purchasing.add_purchaseorder %}
<!-- Show purchasing features -->
{% endif %}
```
## Security Considerations
### 11. Password Policies
```python
# settings.py
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
'OPTIONS': {
'min_length': 8,
}
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
```
### 12. Session Management
```python
# settings.py
SESSION_COOKIE_AGE = 3600 # 1 hour
SESSION_SAVE_EVERY_REQUEST = True
SESSION_EXPIRE_AT_BROWSER_CLOSE = True
```
### 13. Login Attempt Protection
Using django-axes for login attempt tracking:
```python
# settings.py
INSTALLED_APPS = [
# ...
'axes',
]
MIDDLEWARE = [
# ...
'axes.middleware.AxesMiddleware',
]
AUTHENTICATION_BACKENDS = [
'axes.backends.AxesBackend',
'django.contrib.auth.backends.ModelBackend',
]
# Axes configuration
AXES_FAILURE_LIMIT = 5
AXES_COOLOFF_TIME = 1 # hours
AXES_LOCKOUT_TEMPLATE = 'accounts/locked_out.html'
```
This authentication and authorization system provides a robust security framework for the manufacturing application, ensuring that users can only access the modules and functionality they are authorized to use.