CKAN技术问询:如何实现私有数据集元数据对登录用户可见并管控资源下载权限?
实现方案
要实现登录用户查看私有数据集元数据、仅有权限用户可下载资源的需求,直接基于CKAN的插件机制修改权限逻辑即可,具体步骤如下:
1. 放开私有数据集元数据的登录用户访问权限
CKAN默认会限制非管理员/编辑用户查看私有数据集的元数据,我们通过重写package_show权限函数来调整这个逻辑:
from ckan.plugins import implements, IAuthFunctions from ckan.logic.auth.get import package_show as original_package_show def custom_package_show(context, data_dict): # 先执行原权限逻辑,保留基础校验 result = original_package_show(context, data_dict) # 若用户已登录,且原逻辑判定无权限(即私有数据集),则放行元数据查看 if not result.get('success') and context.get('user'): result['success'] = True return result class YourCustomPlugin(object): implements(IAuthFunctions) def get_auth_functions(self): return { 'package_show': custom_package_show }
注:这个修改仅放开元数据查看权限,数据集的编辑、删除等核心权限仍会遵循原逻辑。
2. 拦截无权限用户的资源下载请求
资源下载对应的核心权限是resource_download,同时要配合resource_show确保资源元数据可见但下载被限制:
from ckan.logic.auth.get import resource_show as original_resource_show from ckan.logic.auth.get import resource_download as original_resource_download def custom_resource_show(context, data_dict): result = original_resource_show(context, data_dict) # 登录用户默认可以查看资源元数据,不管有没有下载权限 if context.get('user'): result['success'] = True return result def custom_resource_download(context, data_dict): # 校验用户是否拥有对应数据集的编辑权限(可替换为你自定义的权限) resource_id = data_dict.get('id') resource = context['model'].Resource.get(resource_id) pkg = resource.package if resource else None if not pkg: return {'success': False, 'msg': '资源不存在'} has_permission = context['auth_user_obj'].has_permission('package_update', pkg) if has_permission: return {'success': True} else: return {'success': False, 'msg': '你没有该资源的下载权限'} class YourCustomPlugin(object): implements(IAuthFunctions) def get_auth_functions(self): return { 'package_show': custom_package_show, 'resource_show': custom_resource_show, 'resource_download': custom_resource_download }
3. 前端适配(可选)
为了给用户更直观的提示,可通过模板助手在前端隐藏无权限用户的下载按钮:
from ckan.plugins import implements, ITemplateHelpers from ckan.common import c class YourCustomPlugin(object): implements(ITemplateHelpers) def get_helpers(self): return { 'can_download_resource': can_download_resource } def can_download_resource(resource): pkg = resource.package return c.userobj.has_permission('package_update', pkg)
然后在资源列表模板(比如package/snippets/resource_item.html)中修改:
{% if h.can_download_resource(resource) %} <a href="{{ h.url_for(controller='package', action='resource_download', id=pkg.id, resource_id=resource.id) }}" class="btn btn-primary">下载</a> {% else %} <span class="btn btn-disabled">无下载权限</span> {% endif %}
注意事项
- 权限判断要基于CKAN的官方
auth_user_obj和model对象,不要直接操作数据库,避免破坏原有权限体系 - 若需要更细粒度的权限控制,可以自定义一个
resource_download权限,通过CKAN的权限注册机制添加后替换代码中的package_update - 测试时要覆盖三类场景:未登录用户、登录无权限用户、登录有权限用户,确保逻辑符合预期
内容的提问来源于stack exchange,提问作者Theo Stefou
相关产品推荐
相关产品推荐

