9

मैं रेल पर रूबी (संस्करण 3) में गैर-मानक कस्टम PHP ढांचे में बनाए गए एप्लिकेशन से कोड स्थानांतरित कर रहा हूं। PHP संस्करण में सभी नियंत्रक वास्तव में वसा वाले होते हैं, पतले मॉडल के साथ, जिन्हें मैं हमेशा से असहमत हूं, इसलिए मैं मॉडल स्तर पर रेल के सत्यापन के तरीके का आनंद ले रहा हूं, जो शायद इन वसा नियंत्रकों में क्या हो रहा है का 9 0% वर्तमान में।उपयोगकर्ता अनुमतियों के आधार पर रेल 3 ActiveRecord सत्यापन

एक समस्या का सामना करना पड़ रहा है, और यह सुनिश्चित करने के लिए अनिश्चित है कि मॉडल को बदलने के आधार पर अलग-अलग सत्यापन नियमों के आधार पर यह अलग-अलग सत्यापन नियमों का है। उदाहरण के लिए, एक व्यवस्थापक, या रिकॉर्ड का मूल निर्माता रिकॉर्ड को ध्वजांकित करने के लिए सक्षम होना चाहिए (सॉफ्ट डिलीट) जबकि सभी को नहीं करना चाहिए।

class Something < ActiveRecord::Base 
    ... 
    validates :deleted, :owned_by_active_user => true 
    ... 
end 

class OwnedByActiveUserValidator < ActiveModel::EachValidator 
    validate_each(record, attr_name, attr_value) 
    # Bad idea to have the model know about things such as sessions? 
    unless active_user.admin? || active_user.own?(record) 
     record.errors.add :base, "You do not have permission to delete this record" 
    end 
    end 
end 

के बाद से मॉडल ही (सिद्धांत में) उपयोगकर्ता के लिए जो परिवर्तन कर रहा है के बारे में पता, क्या बात की इस तरह करने के लिए "जिस तरह से रेल" क्या है? क्या मुझे सक्रिय उपयोगकर्ता को रिकार्ड पर वर्चुअल एट्रिब्यूट (वास्तव में डीबी में सहेजा नहीं गया) के रूप में सेट करना चाहिए, या क्या मुझे इन चेक को नियंत्रक में करना चाहिए? मुझे स्वीकार करना है, सक्रिय उपयोगकर्ता पर मॉडल जांच अनुमतियां अजीब लगती हैं, और जब मॉडल का परीक्षण करने की बात आती है तो जटिलता बढ़ जाती है।

एक कारण मैं मॉडल में जितना संभव हो उतना अधिक रखने के इच्छुक हूं, क्योंकि मैं एक एपीआई (ओएथ पर पहुंच गया) और एक वेबसाइट दोनों प्रदान करना चाहता हूं, बिना बहुत अधिक कोड डुप्लिकेट किए, जैसे कि अनुमतियों के प्रकार के प्रकार।

उत्तर

10

यह वास्तव में प्राधिकरण को संभालने के लिए नियंत्रक का काम है, या प्राधिकरण परत को प्राधिकरण देने के लिए है। मॉडल को इसके बारे में पता नहीं होना चाहिए, न ही इस बारे में परवाह करना चाहिए, वर्तमान में कौन लॉग इन है और उसकी अनुमति क्या है - यह नियंत्रक का काम है, या जो कुछ भी सहायक सहायक परत नियंत्रक प्रतिनिधि करता है।

आप new, create, या update_attributes के माध्यम से बड़े पैमाने पर काम करने के लिए :deleted in- attr_accessible बनाना चाहिए। नियंत्रक को अधिकृत उपयोगकर्ता के प्राधिकरणों को अलग से जांचना चाहिए और प्रमाणीकृत उपयोगकर्ता अधिकृत होने पर deleted= अलग से कॉल करना चाहिए।

प्राधिकरण के साथ सहायता करने या प्राधिकरण परत के रूप में कार्य करने के लिए कई प्राधिकरण पुस्तकालयों और ढांचे हैं, जैसे कि cancan

+0

धन्यवाद, मुझे आपके साथ सहमत होना है। मेरे मॉडल को ऐसा करना चाहिए जैसा कि उन्हें बताया गया है (बशर्ते व्यवसाय तर्क उन्हें अनुमति देता है)। मेरे नियंत्रकों को यह तय करना चाहिए कि उन्हें कौन बताता है। मैं बस यह सुनिश्चित कर दूंगा कि मैं गोर के विवरण को यथासंभव सर्वोत्तम रूप से दूर कर सकता हूं। – d11wtq

+0

डोगमा ... मुझे पता है कि यह आमतौर पर किया जाता है, लेकिन ऐसा लगता है कि मॉडल में एक्सेस कंट्रोल डालना एक सुरुचिपूर्ण समाधान है यदि आप मॉडल को अपना डेटा एपीआई/बिजनेस नियम लेयर मानते हैं। यह एक ही मॉडल को एक ही मॉडल को छूने वाले एकाधिक नियंत्रकों में एक ही जानकारी दोहराने से बचाता है।और उद्देश्य के लिए वैधकर्ताओं का उपयोग करना भी वास्तव में सुविधाजनक लगता है - "क्षमा करें, आपको उस फ़ील्ड को संपादित करने की अनुमति नहीं है" जैसी त्रुटियां उत्पन्न कर सकती हैं। हालांकि, वह क्षेत्र पहली जगह में नहीं दिखाया जाना चाहिए था। इच्छा है कि एक ऐसा समाधान था जिसने फॉर्म बिल्डरों के लिए आत्मनिरीक्षण की अनुमति दी। – odigity

+0

आप फ़ॉर्म-मॉडल (डेटाबेस-समर्थित नहीं) कक्षाएं बना सकते हैं जो फॉर्म निर्माता द्वारा आवश्यक सत्यापन और विधियों को लागू करते हैं। – yfeldblum

6

मैं अपने मॉडल में मान्यताओं के बजाय, मेरे नियंत्रक में before_filter के साथ इसे हल कर दूंगा।

class SomethingController < ApplicationController 
    before_filter :require_delete_permission, :only => [:destroy] 

    def destroy 
    # delete the record 
    end 

    private 

    def require_delete_permission 
    unless current_user.is_admin || record.owner == current_user 
     flash[:error] = 'You do not have delete permissions' 
     redirect_to somewhere 
    end 
    end 
end 
+0

मुझे यहां डाउनवोट भी नहीं मिला है। आपका सुझाव प्रभावी ढंग से स्वीकार्य उत्तर कहता है। – d11wtq

+0

सिवाय इसके कि वह फ्लैश में एक संदेश जोड़ रहा है ... रिकॉर्ड को अमान्य नहीं कर रहा है – courtsimas

3

मैं रेल 2.3 में एक ही मुद्दे पर आया हूं और अंत में इस समाधान के साथ आया हूं। आपके मॉडल में आप कुछ एट्रिब्यूट को परिभाषित करते हैं, जिस पर आप सत्यापन चालू/बंद करते हैं। की तुलना में अपने नियंत्रण आप आप तारीख नियंत्रक (जैसे आपके मामले में उपयोगकर्ता विशेषाधिकार के रूप में) के लिए उपलब्ध के आधार पर इस विशेषता सेट इस प्रकार है:

Class Model < ActiveRecord::Base 
    attr_accessor :perform_validation_of_field1 #This is an attribute which controller will use to turn on/off some validation logic depending on the current user 

    validates_presence_of :field1, :if => :perform_validation_of_field1 
    #This validation (or any similar one) will occur only if controller sets model.perform_validation_of_field1 to true. 
end 

Class MyController < ActionController::Base 
    def update 
    @item = Model.find(params[:id]) 
    @item.update_attribute(params[:item]) 

    #The controller decides whether to turn on optional validations depending on current user privileges (without the knowledge of internal implementation of this validation logic) 
    @item.perform_validation_of_field1 = true unless active_user.admin? 

    if @item.save 
     flash[:success] = 'The record has been saved' 
     redirect_to ... 
    else 
     flash.now[:error] = 'The record has not passed validation checks' 
     render :action => :edit 
    end 
    end 

मुझे लगता है कि रेल 3 में यह समान तरीके से किया जा सकता है।

+0

मुझे यह कहना है कि यह पहली छापों पर थोड़ा सा खतरनाक लगता है, लेकिन यदि यह आपके लिए काम कर रहा है तो महान;) – d11wtq

+0

इस दृष्टिकोण में क्या गलत है। खतरनाक के बारे में कुछ भी नहीं है (खेद नहीं है कि इस शब्द से अंग्रेजी में विशेषण कैसे करें :)। हां मैंने एक कोड टाइप किया लेकिन इसे जांच नहीं लिया। मुझे उम्मीद थी कि आपको विचार मिलेगा। विचार का उपयोग करना है: यदि या: जब तक मॉडल में सत्यापन मैक्रोज़ पर पैरामीटर परिभाषित नहीं होते हैं। तो सत्यापन तर्क के कुछ हिस्सों को चालू/बंद किया जा सकता है। नियंत्रक परत जानता है कि किसी मॉडल के लिए किसी विशेष सत्यापन तर्क को सक्षम/अक्षम कैसे करें, लेकिन सत्यापन तर्क कार्यान्वयन के बारे में कुछ भी नहीं जानता है। – cryo28

+0

बेशक आप सत्यापन विकल्पों को एक बड़े हिस्से में जोड़ सकते हैं (प्रत्येक सत्यापन के लिए एक विशेषता को परिभाषित करने की आवश्यकता नहीं है)। तो कृपया http://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html पर एक नज़र डालें और इस पर ध्यान दें: यदि और: यह तय करने से पहले कि यह कोड केवल मेरे लिए काम करता है, सत्यापन के मैक्रोज़ के पैरामीटर एक संयोग के रूप में :) – cryo28

संबंधित मुद्दे