我想检查我的ModelViewSet,如果用户可以创建邀请其他用户到他的公司。我有四个模型:
# Abstract model TimeStampedModel
class TimeStampedModel(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
# abstract = True to enable models inherit from TimeStampedModel
abstract = True
# Custom User model
class User(AbstractUser, TimeStampedModel):
# Make these fields not to be null
email = models.EmailField(unique=True, null=False, blank=False)
first_name = models.CharField(max_length=30, blank=False, null=False)
last_name = models.CharField(max_length=30, blank=False, null=False)
image_path = models.ImageField(upload_to='img', default='profile-pic.webp')
# Assing base user manager for admin panel
objects = CustomUserManager()
USERNAME_FIELD = "username"
REQUIRED_FIELDS = ['email', 'first_name', 'last_name']
# Create your models here.
class Company(TimeStampedModel):
VISIBILITY_CHOICES = (
('hidden', 'Hidden'),
('visible', 'Visible for all'),
)
owner = models.ForeignKey(User, on_delete=models.CASCADE)
name = models.CharField(max_length=50, blank=False, null=False, unique=True)
description = models.TextField(blank=False, null=False)
visibility = models.CharField(max_length=15,
choices=VISIBILITY_CHOICES,
default='visible')
class Meta:
verbose_name = "Company"
verbose_name_plural = 'Companies' # Plural naming
def __str__(self):
return self.name
# Interactions between users and companies
class CompaniesUsers(TimeStampedModel):
STATUS_CHOICES = (
('pending', 'Pending'),
('accepted', 'Accepted'),
('revoked', 'Revoked'),
('rejected', 'Rejected'),
)
company = models.ForeignKey(Company, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
status = models.CharField(default='pending', choices=STATUS_CHOICES)
def __str__(self):
return f"{self.company} - {self.user} - {self.status}"
我创建了自定义权限类,用于检查用户是否可以为该用户创建公司邀请。如果用户不是公司的所有者-则拒绝访问以创建邀请。
我的permissions.py
:
class IsUsersCompany(BasePermission):
def has_permission(self, request, view):
return request.user.is_authenticated
def has_object_permission(self, request, view, obj):
return obj.company.owner == request.user
下面是views.py
中的ModelViewSet:
class CompaniesUsersModelViewSet(ModelViewSet):
queryset = CompaniesUsers.objects.all()
serializer_class = CompaniesUsersModelSerializer
permission_classes = (IsAuthenticated, )
def get_permissions(self):
if self.action == 'create':
self.permission_classes = (IsUsersCompany, )
return super().get_permissions()
但是这个权限类不起作用。任何人都可以为另一个用户创建公司邀请,即使该用户不是公司的所有者
我尝试了什么
我尝试使用obj.company直接从Company模型中获取公司ID。我还尝试了在has_permission方法中检查是否请求.method == 'POST'
我希望当我有一个owner_id = 1的company_1,而id为2的用户尝试为另一个用户创建对company_1的邀请时,它会给他一个访问被拒绝的错误。当id为1的用户执行此操作时-它会创建一个新的邀请
1条答案
按热度按时间djp7away1#
问题似乎出在您的IsUsersCompany权限类。您当前正在检查obj.company.owner == request.user。但是,在创建新邀请的上下文中,obj还不存在,因为您正在创建新对象。
若要在创建邀请时强制此权限,您应该重写has_permission方法并检查其中的条件。您需要确保创建邀请的用户是公司的所有者。
以下是如何修改IsUsersCompany类来实现此目的:
在这段代码中:
在has_permission方法中,我们检查操作是否为'*create'。如果是,我们从请求数据中提取公司ID(确保调整字段名称)。然后我们尝试获取相应的Company对象。如果公司存在,并且其所有者与request.user相同,则返回True。如果公司不存在或者所有者不是request.user,则返回False。对于其他操作,将授予权限。在has_object_permission方法中,可以保留现有的逻辑,检查obj.company.owner是否等于request.user。这确保了用户只能操纵自己的公司。
请确保调整request.data.get('company')中的字段名称,以匹配POST请求数据中使用的名称。