2017-07-06 96 views
0

我試圖在URL調度應用程序中實現動態ACL(包括行級安全性)。 定義Root工廠似乎不夠,因爲我需要爲每個安全端點執行單獨的authz檢查。我的設置如下所示(我用的是pyramid docsmmerickel's tutorials爲指導):金字塔:URL調度(混合)應用程序中的資源樹

config.py

... 
settings = config.registry.settings 
config = Configurator(settings=settings, root_factory=RootPermissionFactory) 
config.set_authentication_policy(CustomAuthenticationPolicy(settings)) 
config.set_authorization_policy(ACLAuthorizationPolicy()) 
... 

views.py

#import ... 

@view_defaults(renderer='json', permission='secured') 
class RecordsView(object): 
    ... 

    @view_config(request_method='GET', route_name='records_by_id') 
    def get(self): 
     record = self.request.context.data 
     if not record: 
      return HTTPNotFound() 
     return record 

    @view_config(request_method='GET', route_name='records') 
    def get_by_owners(self): 
     owner_uids = self.request.params.mixed()['owner_uids'] 
     return records_service.get_records(owner_uids=owner_uids) 

def includeme(config): 
    config.add_route('records', '/records', factory=RecordsResource) 
    config.add_route('records_by_id', 'records/{record_id}', factory=RecordFactory, traverse='{record_id}') 

authorization.py

class RootPermissionFactory(object): 
    __name__ = None 
    __parent__ = None 

    def __acl__(self): 
     return [ 
      (Allow, 'authenticated_principal', 'secured'), 
     ] 

    def __init__(self, request): 
     self.request = request 


class RecordFactory(object): 
    def __init__(self, request): 
     self.request = request 

    def __getitem__(self, key): 
     record_data = records_service.get_record(key) 
     owner = record_data.get('owner_uid') 
     return RecordContext(self.request, owner, record_data) 


class RecordContext(object): 
    def __acl__(self):  
     owner_principal = 'u:{owner}'.format(owner=self.owner) 
     return [ 
      (Allow, owner_principal, 'secured'), 
     ] 

    def __init__(self, request, owner, record_data): 
     self.request = request 
     self.owner = owner 
     self.data = record_data 


class RecordsResource(object): 
    def __acl__(self): 
     request_params = self.request.params.mixed() 
     request_owner_uids = request_params['owner_uids'] 
     authorized_owner_uids = owners_api_service.get_authorized_owners(self.request.user['auth_data']) 
     return [(Allow, 'authenticated_principal', 'secured')]\ 
      if set(authorized_owner_uids) == set(request_owner_uids) else [] 

    def __init__(self, request): 
     self.request = request 

我的問題是以下幾點:

  • 在沒有Model層的情況下利用行級安全檢查是否可以接受?即沒有爲記錄數據設置ORM,並且也沒有簡單的模型來保存數據,所以我必須使用'假'RecordContext類附加__acl__規則並將數據傳遞到視圖
  • 是否可以接受盡管事實上它不是來自Traversal透視圖的資源,並且依賴於查詢參數而不是路徑部分,但將端點視爲資源?

回答

0

我認爲你的兩個問題的答案是:如果它適合你,那麼它是完全可以接受的。我發現很多成功的方法都將URL視爲資源,因爲我有一些工具可以避免使用route_name。例如:

config.add_route('records', '/records', factory=RecordsResource, use_global_views=True) 
config.add_route('records_by_id', 'records/{record_id}', factory=RecordFactory, traverse='{record_id}', use_global_views=True) 

@view_config(context=RecordsResource, renderer='json') 
def records_view(request): 
    return {} 

@view_config(context=RecordContext, renderer='json') 
def record_view(request): 
    return {}