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

11 KiB

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

# 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

# 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

# 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

# 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

# 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

# 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

# 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

<!-- 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

# 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

<!-- 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

# 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

# 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:

# 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.