2017-06-17 64 views
1

我有源和目标基于规则的过渡装饰在django-fsm(有限状态机)运作良好。现在我试图添加权限处理。这看起来很简单,但似乎无论我做什么,都会执行转换,而不管用户的权限或缺少权限。我已经尝试过使用Django权限字符串,并且根据文档,我尝试使用lambda。我已经尝试了所有的这些:Django的FSM:权限不加例外

@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应到任何可调用响应返回真/假,简单地说:

@transition(field=state, source='prog', target='appr', permission=False) 
def approve(self): 

访问过渡时,以下哪应该提高为所有用户TransitionNotAllowed。但是不会 - 即使没有权限的基本用户仍然可以执行转换(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 

我缺少什么?谢谢。

回答

-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") 
0

你实际上应该阅读文档。

permissions documentation

+0

当然,我彻底和彻底地阅读文档。正如我在文章中所描述的,我尝试了文档中描述的两种技术,结果显示在我的文章中。有没有我错过的文档中的某些内容?谢谢。 – shacker

+0

你在错误的句子中应该提出一个TransitionNotAllowed。模型方法中没有权限检查。模型方法甚至不知道用户。 – kmmbvnr

+0

哦!所以它与源/目标验证的工作方式不同。是的,那是我错误的假设。由于这是一个重要的区别,并且不一致,因此文档可能会更清晰。我将'has_transition_permission' doc部分理解为“如果您想检查代码中其他地方的权限......”。建议将其修改为“您必须使用has_transition_permission方法检查权限”(而不是“can”)。谢谢。 – shacker