2017-06-17 63 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