# 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 {% if perms.inventory.add_product %} Add Product {% endif %} {% if perms.inventory.view_product and perms.inventory.change_product %} {% 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 {% if user.is_superuser %} {% endif %} {% if perms.inventory.view_product %} {% endif %} {% if perms.purchasing.view_purchaseorder and perms.purchasing.add_purchaseorder %} {% 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.