我在django-fsm(有限状态机)中有源和目标基于规则的转换装饰器。现在我正在尝试添加权限处理。这似乎很简单,但似乎无论我做什么,都会执行转换,无论用户是否拥有权限。我已尝试使用Django权限字符串,并且根据文档我尝试使用lambda
。我已经尝试了所有这些:
@transition(field=state, source='prog', target='appr', permission='claims.change_claim')
和
@transition(field=state, source='prog', target='appr', permission=lambda instance, user: not user.has_perm('claims.change_claim'),)
并且,作为一个仔细检查,因为permission
应该响应任何可调用的返回True / False,只需:
@transition(field=state, source='prog', target='appr', permission=False)
def approve(self):
在访问转换时,应为所有用户提出TransitionNotAllowed
。但是nope - 即使没有权限的基本用户仍然可以执行转换(claim.approve()
)。
要证明我的权限字符串是正确的:
print(has_transition_perm(claim.approve, request.user))
打印错误。我正在进行如下验证(适用于源/目标):
class ClaimEditForm(forms.ModelForm):
'''
Some users can transition claims through allowable states
'''
def clean_state(self):
state = self.cleaned_data['state']
if state == 'appr':
try:
self.instance.approve()
except TransitionNotAllowed:
raise forms.ValidationError("Claim could not be approved")
return state
class Meta:
model = Claim
fields = (
'state',
)
并且视图处理程序是标准:
if request.method == "POST":
claim_edit_form = ClaimEditForm(request.POST, instance=claim)
if claim_edit_form.is_valid(): # Validate transition rules
我错过了什么?感谢。
答案 0 :(得分:0)
答案 1 :(得分:-1)
问题是,permission
属性的验证与源/目标验证器的验证方式不同。您必须在代码中的其他位置评估装饰器中建立的权限,而不是装饰器引发错误。因此,要从表单执行权限验证,您需要传入用户对象,以init
形式接收用户,然后与has_transition_perm
的结果进行比较。所以这有效:
# model
@transition(field=state, source='prog', target='appr', permission='claims.change_claim')
def approve(self):
....
# view
if request.method == "POST":
claim_edit_form = ClaimEditForm(request.user, request.POST, instance=claim)
....
# form
from django_fsm import has_transition_perm
class ClaimEditForm(forms.ModelForm):
'''
Some users can transition claims through allowable states
(see permission property on claim.approve() decorator)
'''
def __init__(self, user, *args, **kwargs):
# We need to pass the user into the form to validate permissions
self.user = user
super(ClaimEditForm, self).__init__(*args, **kwargs)
def clean_state(self):
state = self.cleaned_data['state']
if state == 'appr':
if not has_transition_perm(self.instance.approve, self.user):
raise forms.ValidationError("You do not have permission for this transition")