问题描述
我想基于Python eve restframework中用户的访问权限实现一个“更复杂”的过滤器。
问题
我们有令牌身份验证,用户帐户在TokenAuth
类中获取。
用户有一些合同,每个合同都有账单。
我要实现一个端点/ bills,该端点显示他的合同账单。
我们使用mongodb
。
为了更好地理解,类似SQL语句"SELECT * FROM bills WHERE bills.contract IN user.contracts"
user { contracts : ["a","b","c"] }
bills { contract: "a" }
背景资料
class TokenAuth(TokenAuthBase):
def check_auth(self, token, allowed_roles, resource, method):
users = app.data.driver.db['users']
TokenAuth.account = users.find_one(lookup)
...
(更新)
用户限制资源访问?(URRA)
对于用户1:n帐单关系的情况,URRA会做。 请参阅 。
在更复杂的情况下,有必要编写一个自定义过滤器查询。 我需要这个选项:)。
更新
我找到了解决方案,请参阅更新的答案。
1楼
那呢?
bills = {
'datasource': {
'source': 'bills',
'filter': {'field1': 'value1', 'field2': 'value2'}
}
}
source
是mongodb集合;
filter
是一个mongodb查询。
它将透明地应用于到达端点的任何请求(在客户端查询之前)。
2楼
多亏了Nicola Iaorcci,我找到了解决方案。
首先,我为每个端点使用一个自定义身份验证类。
class MyCreditNoteAuth(TokenAuthBase):
def check_auth(self, token, allowed_roles, resource, method):
account = app.data.driver.db['users'].find_one({'api_access_token': token})
此方法从mongodb获取用户的帐户,现在我可以访问他的合同ID。
其次,仍然在上层方法中,我根据每个请求更新数据源的筛选器:
mynotes['datasource']['filter']['contract'] = { '$in': account['contracts'] }
现在,客户在给定的端点上只能看到自己的“注释”。
3楼
我认为最好根据每个请求执行此操作。
修改'DOMAIN'
可能会导致以下情况:多个人同时登录并发送请求,并且请求之间的域更改取决于您实施此类操作的方式。
也许这样的事情会工作:
from eve import Eve
from eve.auth import BasicAuth
def pre_get_api_stuff(resource, request, lookup):
username = request.authorization['username']
accounts = app.data.driver.db['accounts']
account = accounts.find_one({'username': username})
if resource == 'notes':
lookup.update({'username': username})
app = Eve(auth=BasicAuth)
app.on_pre_GET += pre_get_api_stuff
4楼
您是否浏览过 ?
乍一看,我想说是通过将用户令牌(或ID,或在您的设置中标识用户的任何内容)与帐单文档一起存储,然后在bills
端点启用URRA,可以解决问题。
5楼
更加完整的示例如下,假设我们在settings.py中具有以下内容
note_schema = {
'user_id': {
'type': 'objectid',
'required': True,
'readonly': True
}
}
user_schema = {
'username': {
'type': 'string',
'required': True,
'unique': True,
},
'password': {
'type': 'string',
'required': True,
},
'token': {
'type': 'string',
'required': True,
}
}
DOMAIN = {
'user': {
'schema': user_schema,
},
'note': {
'schema': note_schema,
},
}
并且auth附带了基于用户名添加过滤器的功能,此处的过滤器逻辑很简单,但是您可以向过滤器中添加任何所需内容
class MyAuth(BasicAuth):
def check_auth(self, token, allowed_roles, resource, method):
username = get_username_from_token(token)
if resource == 'note':
note = app.config['DOMAIN']['note']
user = app.data.driver.db['user'].find_one({'username': username})
note['datasource']['filter'] = {'user_id': user['_id']}
return True