问题
Currently, Eve v0.4 supports User-Restricted Resource Access via the 'auth_field', but it seems to be designed to automatically handle the single-owner case.
How would you enable multi-user restricted access, where a user is allowed to view the resource if their id was included in an array of permitted ids? Potentially with multiple lists for separate read and write permissions.
回答1:
I wrote a small hack for EVE which is adding this functionality. Maybe it's a little bit tricky, but it works.
You need to update your fdec function auth.py for EVE:
def fdec(f):
@wraps(f)
def decorated(*args, **kwargs):
if args:
# resource or item endpoint
resource_name = args[0]
resource = app.config['DOMAIN'][args[0]]
if endpoint_class == 'resource':
public = resource['public_methods']
roles = resource['allowed_roles']
if request.method in ['GET', 'HEAD', 'OPTIONS']:
roles += resource['allowed_read_roles']
else:
roles += resource['allowed_write_roles']
elif endpoint_class == 'item':
public = resource['public_item_methods']
roles = resource['allowed_item_roles']
if roles and isinstance(roles, str):
items = app.data.driver.db[args[0]]
item = items.find_one(kwargs)
roles = item[roles]
if request.method in ['GET', 'HEAD', 'OPTIONS']:
roles += resource['allowed_item_read_roles']
else:
roles += resource['allowed_item_write_roles']
if callable(resource['authentication']):
auth = resource['authentication']()
else:
auth = resource['authentication']
else:
# home
resource_name = resource = None
public = app.config['PUBLIC_METHODS'] + ['OPTIONS']
roles = app.config['ALLOWED_ROLES']
if request.method in ['GET', 'OPTIONS']:
roles += app.config['ALLOWED_READ_ROLES']
else:
roles += app.config['ALLOWED_WRITE_ROLES']
auth = app.auth
if auth and request.method not in public:
if not auth.authorized(roles, resource_name, request.method):
return auth.authenticate()
return f(*args, **kwargs)
return decorated
return fdec
As you can see I added a condition: if isinstance(roles, str) The idea is that when you put a string to allowed_roles instead of list it means that you're pointing to a field in this item, which contains a list of users. So for example I have next scheme and definition of groups:
definition = {
'url': 'groups',
'item_title': 'group',
# only admins and apps are allowed to consume this endpoint
'cache_control': '',
'cache_expires': 0,
'id_field': 'url',
'schema': _schema,
'allowed_item_roles': 'users',
'additional_lookup': {
'url': 'regex("[\w]+")', # to be unique
'field': 'url',
},
}
_schema = {
'name': required_string, # group name
'url': unique_string, # group url - unique id
'users': { # list of users, who registered for this group
'type': 'list',
'scheme': embedded_object('accounts')
},
'items': { # list of items in the group
'type': 'list',
'scheme': embedded_object('items'),
},
'owner': embedded_object('accounts'),
'secret': {'type': 'string'}
}
So as you can see I have a list of users, which is an embedded object of my accounts. The next step is to update roles authentication. Now it should looks like:
def check_auth(self, token, allowed_roles, resource, method):
accounts = app.data.driver.db['accounts']
lookup = {'token': token}
if allowed_roles:
# only retrieve a user if his roles match ``allowed_roles``
lookup['username'] = {'$in': allowed_roles}
account = accounts.find_one(lookup)
if account and 'username' in account:
self.set_request_auth_value(account['username'])
if account:
self.request_auth_value = account['username']
return account is not None
So it checks if username is in allowed roles or not. The last step is to update flaskapp.py in EVE to support strings in allowed_roles
def validate_roles(self, directive, candidate, resource):
""" Validates that user role directives are syntactically and formally
adeguate.
:param directive: either 'allowed_[read_|write_]roles' or
'allow_item_[read_|write_]roles'.
:param candidate: the candidate setting to be validated.
:param resource: name of the resource to which the candidate settings
refer to.
.. versionadded:: 0.0.4
"""
roles = candidate[directive]
if not (isinstance(roles, list) or isinstance(roles, str)):
raise ConfigException("'%s' must be list"
"[%s]." % (directive, resource))
Anyway it's still a workaround and I'm not sure that it will work fast and reliable when you will have thousands of users per item, but for a small amount of users it works.
Hope it will help
回答2:
User Restricted Resource Access is essentially a mechanism for transparently storing the id of the user who created the document along with the document itself. When the user comes back to the endpoint he only sees/edits his own documents. How would you assign multiple "owners" to the document when it is stored?
Have you looked into Role Based Access Control? It does what you are asking for, although at the endpoint (not document) level.
来源:https://stackoverflow.com/questions/24760710/multi-user-restricted-access-with-python-eve