2010-05-21 13 views
14

मैं अपने विकी पर स्क्लेल्चेमी व्यंजनों को देख रहा हूं, लेकिन यह नहीं पता कि मैं कौन सा करने की कोशिश कर रहा हूं उसे लागू करने के लिए सबसे अच्छा कौन सा है।sqlalchemy प्रश्नों के लिए पूर्व फ़िल्टर उपयोगकर्ता पहुंच का सबसे अच्छा तरीका क्या है?

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

आपकी सहायता की सराहना करें। धन्यवाद।

+3

क्या आपने इसे प्राप्त करने के लिए डेटाबेस सुरक्षा प्रणाली का उपयोग करने के बारे में सोचा है? उदाहरण के लिए, ओरेकल इस कार्यक्षमता को अपनी वीपीडी सुविधा (http://www.oracle.com/technology/deploy/security/database-security/virtual-private-database/index.html) के साथ प्रदान करता है। आप अन्य डेटाबेस में भी समान कार्यक्षमता प्राप्त कर सकते हैं (उदा। Http://ddj.com/database/215900773 और http://technet.microsoft.com/en-gb/library/cc966395.aspx)। बस "पंक्ति स्तर सुरक्षा RDBSName" के लिए Google। – stephan

+0

या उन सभी तालिकाओं पर विचार या नियम सेट करें जो उपयुक्त सीमा जोड़ते हैं, और सीधे अंतर्निहित तालिका को पढ़ने की क्षमता के उपयोगकर्ताओं को पट्टी करें। http://www.postgresql.org/docs/8.4/interactive/rules.html –

उत्तर

2

नीचे सभी मॉडल प्रश्नों (संबंधों सहित) फ़िल्टर करने के लिए सरलीकृत परिभाषित क्वेरी कन्स्ट्रक्टर है। आप इसे query_cls पैरामीटर sessionmaker पर पास कर सकते हैं। उपयोगकर्ता आईडी पैरामीटर को वैश्विक होने की आवश्यकता नहीं है जब तक कि यह पहले से उपलब्ध होने पर सत्र का निर्माण हो।

class HackedQuery(Query): 

    def get(self, ident): 
     # Use default implementation when there is no condition 
     if not self._criterion: 
      return Query.get(self, ident) 
     # Copied from Query implementation with some changes. 
     if hasattr(ident, '__composite_values__'): 
      ident = ident.__composite_values__() 
     mapper = self._only_mapper_zero(
        "get() can only be used against a single mapped class.") 
     key = mapper.identity_key_from_primary_key(ident) 
     if ident is None: 
      if key is not None: 
       ident = key[1] 
     else: 
      from sqlalchemy import util 
      ident = util.to_list(ident) 
     if ident is not None: 
      columns = list(mapper.primary_key) 
      if len(columns)!=len(ident): 
       raise TypeError("Number of values doen't match number " 
           'of columns in primary key') 
      params = {} 
      for column, value in zip(columns, ident): 
       params[column.key] = value 
      return self.filter_by(**params).first() 


def QueryPublic(entities, session=None): 
    # It's not directly related to the problem, but is useful too. 
    query = HackedQuery(entities, session).with_polymorphic('*') 
    # Version for several entities needs thorough testing, so we 
    # don't use it yet. 
    assert len(entities)==1, entities 
    cls = _class_to_mapper(entities[0]).class_ 
    public_condition = getattr(cls, 'public_condition', None) 
    if public_condition is not None: 
     query = query.filter(public_condition) 
    return query 

यह केवल एक मॉडल प्रश्नों के लिए काम करता है, और वहाँ बहुत काम यह अन्य मामलों के लिए उपयुक्त बनाने के लिए है। मैं एक विस्तृत संस्करण देखना चाहता हूं क्योंकि इसमें अधिकांश वेब अनुप्रयोगों के लिए कार्यक्षमता होनी चाहिए। यह प्रत्येक मॉडल वर्ग में संग्रहीत निश्चित स्थिति का उपयोग करता है, इसलिए आपको इसे अपनी आवश्यकताओं में संशोधित करना होगा।

+1

इसलिए मैंने http://www.sqlalchemy.org/trac/wiki/UsageRecipes/PreFilteredQuery के संयोजन के साथ आपके उत्तर का पालन किया। सत्र वर्ग के स्तर पर query_cls को निर्दिष्ट करने का कोई तरीका है जैसा कि सत्र निर्माता के मानते हैं? सभी मॉडलों में यह कॉलम नहीं है जिसे मैं फ़िल्टर करना चाहता हूं। – steve

+0

ओह, मैंने मॉडल में क्वेरी = सत्र.query_property (FilterByUserQuery) किया था। बहुत धन्यवाद। – steve

1

यहां एक बहुत बेवकूफ कार्यान्वयन है जो मानता है कि उपयोगकर्ता द्वारा संग्रहीत विशेषता/संपत्ति self.current_user लॉग इन है।

class YourBaseRequestHandler(object): 

    @property 
    def current_user(self): 
     """The current user logged in.""" 
     pass 

    def query(self, session, entities): 
     """Use this method instead of :method:`Session.query() 
     <sqlalchemy.orm.session.Session.query>`. 

     """ 
     return session.query(entities).filter_by(user_id=self.current_user.id) 
1

मैं एक SQLAlchemy विस्तार मुझे लगता है कि आप क्या कर रहे हैं का वर्णन करता है लिखा है: https://github.com/mwhite/multialchemy

यह Query._from_obj और QueryContext._froms गुण में परिवर्तन को प्रॉक्सी है, जो है, जहां टेबल से अंततः तैयार हो जाओ चयन करने के लिए ऐसा करता है ।

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