403 Forbidden Error for Django View Despite Permissions on Custom User Model (in userauths app)

I’m working on a Django project where I’ve implemented a custom user model (CustomUser) in the userauths app. The custom user model uses email as the unique identifier instead of the username. My goal is to allow certain users with specific permissions (change_product or delete_product) to edit or delete a product. However, even after assigning the appropriate permissions to the user, they’re still receiving a 403 Forbidden error.

I’ve followed Django’s documentation for creating a custom user model, but I suspect there’s a misconfiguration or step I’ve overlooked. Here’s the detailed setup:


Custom User Model and Manager (in userauths app):

Below is the code for my custom user model and its manager:

# userauths/models.py
from django.contrib.auth.models import AbstractUser, BaseUserManager
from django.db import models
from django.utils.translation import gettext_lazy as _

class CustomUserManager(BaseUserManager):
    def _create_user(self, email, password=None, **extra_fields):
        if not email:
            raise ValueError('The given email must be set')
        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_user(self, email, password=None, **extra_fields):
        extra_fields.setdefault('is_staff', False)
        extra_fields.setdefault('is_superuser', False)
        return self._create_user(email, password, **extra_fields)

    def create_superuser(self, email, password=None, **extra_fields):
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)

        if not extra_fields.get('is_staff'):
            raise ValueError('Superuser must have is_staff=True.')
        if not extra_fields.get('is_superuser'):
            raise ValueError('Superuser must have is_superuser=True.')

        return self._create_user(email, password, **extra_fields)


class CustomUser(AbstractUser):
    username = None
    email = models.EmailField(_('email address'), unique=True)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    objects = CustomUserManager()

I’ve replaced the default username field with email and ensured the necessary fields like is_staff and is_superuser are included.

In my settings.py, I have the following line to specify the custom user model:

AUTH_USER_MODEL = 'userauths.CustomUser'

Product Model (in core app):

Here’s the Product model located in the core app:

# core/models.py
from django.db import models
from shortuuidfield import ShortUUIDField
from django.utils.safestring import mark_safe
from ckeditor_uploader.fields import RichTextUploadingField
from taggit.managers import TaggableManager
from userauths.models import CustomUser  # Importing the custom user model

class Product(models.Model):
    pid = ShortUUIDField(length=10, max_length=100, prefix="prd", alphabet="abcdef")
    user = models.ForeignKey(CustomUser, on_delete=models.SET_NULL, null=True)
    title = models.CharField(max_length=100, default="Apple")
    image = models.ImageField(upload_to="uploads/", default="product.jpg")
    description = RichTextUploadingField(null=True, blank=True, default="This is a product")
    price = models.DecimalField(max_digits=10, decimal_places=2, default=1.99)
    old_price = models.DecimalField(max_digits=10, decimal_places=2, default=2.99)
    status = models.BooleanField(default=True)
    date = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.title

Views for Editing and Deleting Products:

Here’s the relevant view logic for editing and deleting a product:

# useradmin/views.py
from django.shortcuts import get_object_or_404, redirect, render
from django.contrib.auth.decorators import login_required, user_passes_test
from core.models import Product

@login_required
@user_passes_test(lambda user: user.is_staff)
def edit_product(request, pid):
    product = get_object_or_404(Product, pid=pid)
    if request.method == "POST":
        form = AddProductForm(request.POST, request.FILES, instance=product)
        if form.is_valid():
            form.save()
            return redirect("useradmin:vendordashboard")
    else:
        form = AddProductForm(instance=product)

    context = {"form": form, "product": product}
    return render(request, "useradmin/edit-product.html", context)


@login_required
@user_passes_test(lambda user: user.is_staff)
def delete_product(request, pid):
    product = get_object_or_404(Product, pid=pid)
    product.delete()
    return redirect("useradmin:vendordashboard")

Problem:

  1. I’ve assigned the change_product and delete_product permissions to the user via the Django Admin Panel.
  2. The user is marked as is_staff=True.
  3. Despite this, the user receives a 403 Forbidden error when trying to access the edit_product or delete_product views.

What I’ve Tried:

  1. Verified the permissions are correctly assigned using:

    user.get_all_permissions()
    

    The correct permissions (e.g., core.change_product, core.delete_product) appear in the output.

  2. Confirmed the custom user model is being used by checking:

    from django.contrib.auth import get_user_model
    print(get_user_model())
    

    This outputs userauths.models.CustomUser.

  3. Checked the is_staff field is set to True.

  4. Tried replacing @user_passes_test with @permission_required:

    from django.contrib.auth.decorators import permission_required
    
    @login_required
    @permission_required('core.change_product', raise_exception=True)
    def edit_product(request, pid):
        ...
    

    This also resulted in a 403 Forbidden error.


Expected Behavior:

If a user has the appropriate change_product or delete_product permission, they should be able to access the respective views.


Actual Behavior:

Even after assigning the correct permissions, the views return a 403 Forbidden error.


Environment:

  • Django version: 5.1.3
  • Python version: 3.12.5
  • Database: SQLite
  • Apps:
    • userauths for the custom user model
    • core for the product model

Question:

What could be causing this 403 Forbidden error even though the user has the required permissions? Is there an additional step I need to perform when using a custom user model with permissions?


Вернуться на верх