def member_delete(context, data_dict=None): ''' Remove an object (e.g. a user, dataset or group) from a group. Custom organization permission handling added on top of CKAN's own member_create action. ''' _log_action('Member', 'delete', context['user'], data_dict.get('id')) # NOTE! CHANGING CKAN ORGANIZATION PERMISSIONS authz.ROLE_PERMISSIONS = settings.ROLE_PERMISSIONS user = context['user'] user_id = authz.get_user_id_for_username(user, allow_none=True) group_id, target_name, obj_type = _get_or_bust(data_dict, ['id', 'object', 'object_type']) if obj_type == 'user': # get user's role for this group user_role = utils.get_member_role(group_id, user_id) target_id = authz.get_user_id_for_username(target_name, allow_none=True) # get target's role for this group target_role = utils.get_member_role(group_id, target_id) if authz.is_sysadmin(user): # Sysadmin can do anything. pass elif not settings.ORGANIZATION_MEMBER_PERMISSIONS.get((user_role, target_role, 'member', user_id == target_id), False): raise ckan.logic.NotAuthorized(_("You don't have permission to remove this user.")) return ckan.logic.action.delete.member_delete(context, data_dict)
def basket_list(context, data_dict): """List all baskets for user :param user_id: The id of the user for whom to list the baskets (only admin) :type user_id: string :returns: """ model = context['model'] user = context['user'] user_id = data_dict.get( 'user_id', authz.get_user_id_for_username(user, allow_none=True)) if not user_id: return [] if data_dict.get('user_id'): user = model.User.get(user_id) if user is None: raise tk.ObjectNotFound('User was not found') user_id = user.id q = model.Session.query(Basket).filter(Basket.user_id == user_id) return [basket.as_dict() for basket in q.all()]
def member_create(context, data_dict=None): ''' Make an object (e.g. a user, dataset or group) a member of a group. Custom organization permission handling added on top of CKAN's own member_create action. ''' _log_action('Member', 'create', context['user'], data_dict.get('id')) # NOTE! CHANGING CKAN ORGANIZATION PERMISSIONS authz.ROLE_PERMISSIONS = settings.ROLE_PERMISSIONS user = context['user'] user_id = authz.get_user_id_for_username(user, allow_none=True) group_id, obj_id, obj_type, capacity = _get_or_bust(data_dict, ['id', 'object', 'object_type', 'capacity']) # get role the user has for the group user_role = utils.get_member_role(group_id, user_id) if obj_type == 'user': # get role for the target of this role change target_role = utils.get_member_role(group_id, obj_id) if target_role is None: target_role = capacity if authz.is_sysadmin(user): # Sysadmin can do anything pass elif not settings.ORGANIZATION_MEMBER_PERMISSIONS.get((user_role, target_role, capacity, user_id == obj_id), False): raise ckan.logic.NotAuthorized(_("You don't have permission to modify roles for this organization.")) return ckan.logic.action.create.member_create(context, data_dict)
def group_list_authz(context, data_dict): """Return the list of groups that the user is authorized to edit. Replaces the core authz method of the same name.""" user = context["user"] model = context["model"] user_id = authz.get_user_id_for_username(user, allow_none=True) toolkit.check_access("group_list_authz", context, data_dict) if GroupAdmin.is_user_group_admin(model.Session, user_id): q = ( model.Session.query(model.Group) .filter(model.Group.is_organization == False) .filter(model.Group.state == "active") ) groups = q.all() group_list = model_dictize.group_list_dictize(groups, context) return group_list else: # defer to core method return core_group_list_authz(context, data_dict)
def basket_create(context, data_dict): """Create a new basket :param user_id: The id of the user to create the basket for (only admin) :type user_id: string :param element_type: The type of the basket elements (e.g. package, resource, subset) (optional) :type element_type: string :returns: """ tk.check_access('basket_create', context, data_dict) model = context['model'] user = context['user'] user_dct = tk.get_action("user_show")(context, {"id": user}) # Default element_type if 'element_type' not in data_dict: data_dict['element_type'] = "package" # sysadmins are allowed to pass user_id if 'user_id' not in data_dict or not user_dct.get("sysadmin"): data_dict['user_id'] = user_dct.get('id') else: # check if given user exists data_dict['user_id'] = authz.get_user_id_for_username( data_dict['user_id'], allow_none=True) basket = d.table_dict_save(data_dict, Basket, context) if not context.get('defer_commit'): model.repo.commit() return basket.as_dict()
def _has_user_permission_for_some_group(user_name, permission): """Check if the user has the given permission for any group. """ user_id = authz.get_user_id_for_username(user_name, allow_none=True) if not user_id: return False roles = authz.get_roles_with_permission(permission) if not roles: return False # get any groups the user has with the needed role q = model.Session.query(model.Member) \ .filter(model.Member.table_name == 'user') \ .filter(model.Member.state == 'active') \ .filter(model.Member.capacity.in_(roles)) \ .filter(model.Member.table_id == user_id) group_ids = [] for row in q.all(): group_ids.append(row.group_id) # if not in any groups has no permissions if not group_ids: return False # see if any of the groups are active q = model.Session.query(model.Group) \ .filter(model.Group.state == 'active') \ .filter(model.Group.id.in_(group_ids)) return bool(q.count())
def organization_list_without_memberships(context, data_dict): model = context['model'] if data_dict.get('id'): user_obj = model.User.get(data_dict['id']) if not user_obj: raise NotFound user = user_obj.name else: user = context['user'] logic.check_access('organization_list_without_memberships', context, data_dict) user_id = authz.get_user_id_for_username(user, allow_none=True) if not user_id: return [] subquery = model.Session.query(model.Group.id)\ .filter(model.Member.table_name == 'user')\ .filter(model.Member.table_id == user_id)\ .filter(model.Group.id == model.Member.group_id)\ .filter(model.Member.state.in_(['active', 'pending'])) \ .distinct(model.Group.id) \ .filter(model.Group.is_organization == True) # noqa groups = model.Session.query(model.Group) \ .filter(model.Group.id.notin_(subquery)).all() return model_dictize.group_list_dictize(groups, context, with_package_counts=asbool(data_dict.get('include_dataset_count')))
def search_list(context, data_dict): ''' List the search history :param limit: The number of items to show (optional, default: 10) :type limit: int ''' if db.search_history_table is None: db.init_db(context['model']) tk.check_access('search_history_list', context, data_dict) username = context.get('user') user = authz.get_user_id_for_username(username, allow_none=False) # Get the limit and put a hard upper limit on it limit = data_dict.get('limt', 10) if limit > 25: limit = 25 history = db.SearchHistory.search_history(user_id=user, limit=limit) result = [] if history: for item in history: data_dict = db.table_dictize(item, context) data_dict['params'] = json.loads(data_dict.get('params')) result.append(data_dict) return result
def validator(key, data, errors, context): if context.get('group') is not None: old_organization = get_action('organization_show')(context, {'id': context['group'].id}) old_parent_group_names = [org['name'] for org in old_organization.get('groups', [])] else: old_parent_group_names = [] user = context['user'] # Uses CKAN core function to specify parent, in html groups__0__name actual_key = ("groups", 0, "name") if data.get(actual_key): if not authz.is_sysadmin(user): selected_organization = get_action('organization_show')(context, {'id': data[actual_key]}) if data[actual_key] and data[actual_key] not in old_parent_group_names: admin_in_orgs = model.Session.query(model.Member).filter(model.Member.state == 'active')\ .filter(model.Member.table_name == 'user')\ .filter(model.Member.capacity == 'admin')\ .filter(model.Member.table_id == authz.get_user_id_for_username(user, allow_none=True)) if not any(selected_organization['name'] == admin_org.group.name for admin_org in admin_in_orgs): errors[key].append(_('User %s is not administrator in the selected parent organization') % user) # Remove parent_org from data as it is missing from the form data.pop(key, None) # Stop validation if error has happened raise StopOnError
def before_search(self, search_params): # If the current context has a group member item, # update the search parameters if toolkit.c.group: # Collect a member list of all members of the group in context member_list = toolkit.get_action('member_list')( data_dict={ 'id': toolkit.c.group.name }) for member in member_list: # If a person is logged in and the second value # in the tuple is user if toolkit.c.userobj != None and member[1] == "user": # Get the UID from the currently logged in user username = authz.get_user_id_for_username(toolkit.c.user) # If the UID matches the member UID, set the # search parameters to show public and private datasets. if member[0] == username: search_params['fq'] = '' return search_params # Return default search parameters if not in a group return search_params
def restricted_resource_show(context, data_dict=None): # Ensure user who can edit the package can see the resource resource = data_dict.get('resource', context.get('resource', {})) if not resource: resource = logic_auth.get_resource_object(context, data_dict) if type(resource) is not dict: resource = resource.as_dict() if authz.is_authorized('package_update', context, { 'id': resource.get('package_id') }).get('success'): return ({'success': True}) # custom restricted check auth_user_obj = context.get('auth_user_obj', None) user_name = "" if auth_user_obj: user_name = auth_user_obj.as_dict().get('name', '') else: if authz.get_user_id_for_username(context.get('user'), allow_none=True): user_name = context.get('user', '') package = data_dict.get('package', {}) if not package: model = context['model'] package = model.Package.get(resource.get('package_id')) package = package.as_dict() return logic.restricted_check_user_resource_access(user_name, resource, package)
def group_list_authz(context, data_dict): '''Return the list of groups that the user is authorized to edit. :param available_only: remove the existing groups in the package (optional, default: ``False``) :type available_only: boolean :param am_member: if ``True`` return only the groups the logged-in user is a member of, otherwise return all groups that the user is authorized to edit (for example, sysadmin users are authorized to edit all groups) (optional, default: ``False``) :type am-member: boolean :returns: list of dictized groups that the user is authorized to edit :rtype: list of dicts ''' model = context['model'] user = context['user'] available_only = data_dict.get('available_only', False) am_member = data_dict.get('am_member', False) group_type = data_dict.get('type', 'group') _check_access('group_list_authz', context, data_dict) sysadmin = authz.is_sysadmin(user) roles = authz.get_roles_with_permission('manage_group') if not roles: return [] user_id = authz.get_user_id_for_username(user, allow_none=True) if not user_id: return [] if not sysadmin or am_member: q = model.Session.query(model.Member) \ .filter(model.Member.table_name == 'user') \ .filter(model.Member.capacity.in_(roles)) \ .filter(model.Member.table_id == user_id) \ .filter(model.Member.state == 'active') group_ids = [] for row in q.all(): group_ids.append(row.group_id) if not group_ids: return [] q = model.Session.query(model.Group) \ .filter(model.Group.is_organization == False) \ .filter(model.Group.state == 'active') \ .filter(model.Group.type == group_type) if not sysadmin or am_member: q = q.filter(model.Group.id.in_(group_ids)) groups = q.all() if available_only: package = context.get('package') if package: groups = set(groups) - set(package.get_groups()) group_list = model_dictize.group_list_dictize(groups, context) return group_list
def organization_create(context, data_dict=None): user = context['user'] user = authz.get_user_id_for_username(user, allow_none=True) if user and authz.check_config_permission('user_create_organizations'): return {'success': True} return {'success': False, 'msg': _('User %s not authorized to create organizations') % user}
def organization2_create(context, data_dict=None): user = context['user'] user = authz.get_user_id_for_username(user, allow_none=True) if user and authz.check_config_permission('user_create_organizations2'): return {'success': True} return {'success': False, 'msg': _('User %s not authorized to create organizations2') % user}
def decorate_has_user_permission_for_group_or_org(group_id, user_name, permission): user_id = authz.get_user_id_for_username(user_name, allow_none=True) if not user_id: return False if CadastaAdmin.is_user_cadasta_admin(model.Session, user_id): return True return method(group_id, user_name, permission)
def restricted_get_username_from_context(context): auth_user_obj = context.get('auth_user_obj', None) user_name = '' if auth_user_obj: user_name = auth_user_obj.as_dict().get('name', '') else: if authz.get_user_id_for_username(context.get('user'), allow_none=True): user_name = context.get('user', '') return user_name
def search(self): from ckan.lib.search import SearchError package_type = self._guess_package_type() if (package_type == 'harvest'): user = authz.get_user_id_for_username(c.user, allow_none=True) if not user: base.abort(401, _('Not authorized to see this page')) return super(DGEPackageController, self).search()
def group_create(context: Context, data_dict: Optional[DataDict] = None) -> AuthResult: user = context['user'] user = authz.get_user_id_for_username(user, allow_none=True) if user and authz.check_config_permission('user_create_groups'): return {'success': True} return {'success': False, 'msg': _('User %s not authorized to create groups') % user}
def group_create(context, data_dict=None): user = context['user'] user = authz.get_user_id_for_username(user, allow_none=True) if user and authz.check_config_permission('user_create_groups'): if authz.config.get('ckan.gov_theme.is_back'): return {'success': True} else: return {'success': False} return {'success': False, 'msg': _('User %s not authorized to create groups') % user}
def initiatives_get_username_from_context(context): auth_user_obj = context.get("auth_user_obj", None) user_name = "" if auth_user_obj: user_name = auth_user_obj.as_dict().get("name", "") else: if authz.get_user_id_for_username(context.get("user"), allow_none=True): user_name = context.get("user", "") return user_name
def app_create(context, data_dict=None): user = context['user'] user = authz.get_user_id_for_username(user, allow_none=True) if user and authz.check_config_permission('user_create_apps'): return {'success': True} return { 'success': False, 'msg': _(u'Usuário %s não autorizado para criar um app') % user }
def decorate_has_user_permission_for_group_or_org(group_id, user_name, permission): user_id = authz.get_user_id_for_username(user_name, allow_none=True) if not user_id: return False if permission == 'workflow': if is_user_authorized_workflow(group_id, user_id, permission): return True else: return False return method(group_id, user_name, permission)
def inventory_entry_list_for_user(context, data_dict): # TODO @palcu: DRY the code below from organization_list_for_user model = context['model'] user = context['user'] check_access('organization_list_for_user', context, data_dict) sysadmin = authz.is_sysadmin(user) orgs_q = model.Session.query(InventoryEntry).join(model.Group) \ .filter(model.Group.is_organization == True) \ .filter(model.Group.state == 'active') if not sysadmin: # for non-Sysadmins check they have the required permission # NB 'edit_group' doesn't exist so by default this action returns just # orgs with admin role permission = data_dict.get('permission', 'edit_group') roles = authz.get_roles_with_permission(permission) if not roles: return [] user_id = authz.get_user_id_for_username(user, allow_none=True) if not user_id: return [] q = model.Session.query(model.Member, model.Group) \ .filter(model.Member.table_name == 'user') \ .filter(model.Member.capacity.in_(roles)) \ .filter(model.Member.table_id == user_id) \ .filter(model.Member.state == 'active') \ .join(model.Group) group_ids = set() roles_that_cascade = \ authz.check_config_permission('roles_that_cascade_to_sub_groups') for member, group in q.all(): if member.capacity in roles_that_cascade: group_ids |= set([ grp_tuple[0] for grp_tuple in group.get_children_group_hierarchy( type='organization') ]) group_ids.add(group.id) if not group_ids: return [] orgs_q = orgs_q.filter(model.Group.id.in_(group_ids)) return [table_dictize(obj, context) for obj in orgs_q.all()]
def inventory_entry_list_for_user(context, data_dict): # TODO @palcu: DRY the code below from organization_list_for_user model = context['model'] user = context['user'] check_access('organization_list_for_user', context, data_dict) sysadmin = authz.is_sysadmin(user) orgs_q = model.Session.query(InventoryEntry).join(model.Group) \ .filter(model.Group.is_organization == True) \ .filter(model.Group.state == 'active') if not sysadmin: # for non-Sysadmins check they have the required permission # NB 'edit_group' doesn't exist so by default this action returns just # orgs with admin role permission = data_dict.get('permission', 'edit_group') roles = authz.get_roles_with_permission(permission) if not roles: return [] user_id = authz.get_user_id_for_username(user, allow_none=True) if not user_id: return [] q = model.Session.query(model.Member, model.Group) \ .filter(model.Member.table_name == 'user') \ .filter(model.Member.capacity.in_(roles)) \ .filter(model.Member.table_id == user_id) \ .filter(model.Member.state == 'active') \ .join(model.Group) group_ids = set() roles_that_cascade = \ authz.check_config_permission('roles_that_cascade_to_sub_groups') for member, group in q.all(): if member.capacity in roles_that_cascade: group_ids |= set([ grp_tuple[0] for grp_tuple in group.get_children_group_hierarchy(type='organization') ]) group_ids.add(group.id) if not group_ids: return [] orgs_q = orgs_q.filter(model.Group.id.in_(group_ids)) return [table_dictize(obj, context) for obj in orgs_q.all()]
def validator(key, data, errors, context): if context.get('group') is not None: old_organization = get_action('organization_show')( context, { 'id': context['group'].id }) old_parent_group_names = [ org['name'] for org in old_organization.get('groups', []) ] else: old_parent_group_names = [] user = context['user'] # Uses CKAN core function to specify parent, in html groups__0__name actual_key = ("groups", 0, "name") if data.get(actual_key): if not authz.is_sysadmin(user): selected_organization = get_action('organization_show')( context, { 'id': data[actual_key] }) if data[actual_key] and data[ actual_key] not in old_parent_group_names: admin_in_orgs = model.Session.query(model.Member).filter(model.Member.state == 'active')\ .filter(model.Member.table_name == 'user')\ .filter(model.Member.capacity == 'admin')\ .filter(model.Member.table_id == authz.get_user_id_for_username(user, allow_none=True)) if not any(selected_organization['name'] == admin_org.group.name for admin_org in admin_in_orgs): errors[key].append( _('User %s is not administrator in the selected parent organization' ) % user) # Remove parent_org from data as it is missing from the form data.pop(key, None) # Stop validation if error has happened raise StopOnError
def _service_organizations(self): ''' modified from organization_list_for_user ''' context = {'user': c.user} data_dict = {'permission': 'create_dataset'} user = context['user'] toolkit.check_access('organization_list_for_user', context, data_dict) sysadmin = authz.is_sysadmin(user) orgs_q = model.Session.query(model.Group) \ .filter(model.Group.is_organization == True) \ .filter(model.Group.state == 'active') # noqa if not sysadmin: # for non-Sysadmins check they have the required permission permission = data_dict.get('permission', 'edit_group') roles = authz.get_roles_with_permission(permission) if not roles: return [] user_id = authz.get_user_id_for_username(user, allow_none=True) if not user_id: return [] q = model.Session.query(model.Member) \ .filter(model.Member.table_name == 'user') \ .filter(model.Member.capacity.in_(roles)) \ .filter(model.Member.table_id == user_id) \ .filter(model.Member.state == 'active') group_ids = [] for row in q.all(): group_ids.append(row.group_id) if not group_ids: return [] orgs_q = orgs_q.filter(model.Group.id.in_(group_ids)) orgs_q = orgs_q.join(model.GroupExtra).filter(model.GroupExtra.key == u'public_adminstration_organization') \ .filter(model.GroupExtra.value == u'true') # YTP modification return model_dictize.group_list_dictize(orgs_q.all(), context)
def get_user_role_role_in_org(org_id): context = _get_context() user = context.get('user') user_id = get_user_id_for_username(user, allow_none=True) if not org_id: return None if not user_id: return None q = m.Session.query(m.Member) \ .filter(m.Member.group_id == org_id) \ .filter(m.Member.table_name == 'user') \ .filter(m.Member.state == 'active') \ .filter(m.Member.table_id == user_id) out = q.first() role = out.capacity return role
def search_add(context, data_dict): ''' Add an item to the search_history for the current user. :param params: Search query to add to history :type params: string ''' tk.check_access('search_history_add', context, data_dict) if db.search_history_table is None: db.init_db(context['model']) data, errors = df.validate(data_dict, schema_add, context) username = context.get('user') user_id = authz.get_user_id_for_username(username, allow_none=False) search_history = db.SearchHistory() search_history.params = data.get('params') search_history.user_id = user_id session = context['session'] session.add(search_history) session.commit() return db.table_dictize(search_history, context)
def organization_update(context, data_dict): """ This overrides CKAN's auth function to make sure that user has permission to use a specific parent organization. """ group = logic_auth.get_group_object(context, data_dict) user = context['user'] # Check that user has admin permissions in selected parent organizations if data_dict and data_dict.get('groups'): admin_in_orgs = model.Session.query(model.Member).filter(model.Member.state == 'active').filter(model.Member.table_name == 'user') \ .filter(model.Member.capacity == 'admin').filter(model.Member.table_id == authz.get_user_id_for_username(user, allow_none=True)) for parent_org in data_dict['groups']: if any(parent_org['name'] == admin_org.group.name for admin_org in admin_in_orgs): break else: return { 'success': False, 'msg': _('User %s is not administrator in the selected parent organization' ) % user } if (data_dict and 'save' in data_dict and data_dict.get('public_adminstration_organization', None) != group.extras.get('public_adminstration_organization', None)): return { 'success': False, 'msg': _('User %s is not allowed to change the public organization option' ) % user } authorized = authz.has_user_permission_for_group_or_org( group.id, user, 'update') if not authorized: return { 'success': False, 'msg': _('User %s not authorized to edit organization %s') % (user, group.id) } else: return {'success': True}
def search_add(context, data_dict): username = context.get('user') user = authz.get_user_id_for_username(username, allow_none=True) if user is None: return {'success': False, 'msg': 'Not authorized'} return {'success': True}
def group_list_authz(context, data_dict): ''' Return the list of groups that the user is authorized to edit. Action "group_list_authz" ovewrites core "group_list_authz" action. It does so in order to allow users, other than the sysadmin, add/delete members to/from a thematic group. The only precondition to that right, is the user having at least editor rights for at least one organization. :param available_only: remove the existing groups in the package (optional, default: ``False``) :type available_only: boolean :param am_member: if True return only the groups the logged-in user is a member of, otherwise return all groups that the user is authorized to edit (for example, sysadmin users are authorized to edit all groups) (optional, default: False) :type am-member: boolean :returns: list of dictized groups that the user is authorized to edit :rtype: list of dicts ''' model = context['model'] user = context['user'] available_only = data_dict.get('available_only', False) am_member = data_dict.get('am_member', False) _check_access('group_list_authz', context, data_dict) sysadmin = new_authz.is_sysadmin(user) roles = new_authz.get_roles_with_permission('update_dataset') if not roles: return [] user_id = new_authz.get_user_id_for_username(user, allow_none=True) if not user_id: return [] if not sysadmin or am_member: q = model.Session.query(model.Member) \ .filter(model.Member.table_name == 'user') \ .filter(model.Member.capacity.in_(roles)) \ .filter(model.Member.table_id == user_id) group_ids = [] for row in q.all(): group_ids.append(row.group_id) if not group_ids: return [] if context.get('package'): package_org = context.get('package').owner_org if package_org not in group_ids: return [] q = model.Session.query(model.Group) \ .filter(model.Group.is_organization == False) \ .filter(model.Group.state == 'active') groups = q.all() if available_only: package = context.get('package') if package: groups = set(groups) - set(package.get_groups()) group_list = model_dictize.group_list_dictize(groups, context) return group_list
def organization_list_for_user(context, data_dict): '''Return the organizations that the user has a given permission for. By default this returns the list of organizations that the currently authorized user can edit, i.e. the list of organizations that the user is an admin of. Specifically it returns the list of organizations that the currently authorized user has a given permission (for example: "manage_group") against. When a user becomes a member of an organization in CKAN they're given a "capacity" (sometimes called a "role"), for example "member", "editor" or "admin". Each of these roles has certain permissions associated with it. For example the admin role has the "admin" permission (which means they have permission to do anything). The editor role has permissions like "create_dataset", "update_dataset" and "delete_dataset". The member role has the "read" permission. This function returns the list of organizations that the authorized user has a given permission for. For example the list of organizations that the user is an admin of, or the list of organizations that the user can create datasets in. This takes account of when permissions cascade down an organization hierarchy. :param permission: the permission the user has against the returned organizations, for example ``"read"`` or ``"create_dataset"`` (optional, default: ``"edit_group"``) :type permission: string :returns: list of organizations that the user has the given permission for :rtype: list of dicts ''' model = context['model'] user = context['user'] _check_access('organization_list_for_user', context, data_dict) sysadmin = authz.is_sysadmin(user) orgs_q = model.Session.query(model.Group) \ .filter(model.Group.is_organization == True) \ .filter(model.Group.state == 'active') if not sysadmin: # for non-Sysadmins check they have the required permission # NB 'edit_group' doesn't exist so by default this action returns just # orgs with admin role permission = data_dict.get('permission', 'edit_group') roles = AuthRole.get_role_with_permission(permission) if not roles: return [] user_id = authz.get_user_id_for_username(user, allow_none=True) if not user_id: return [] memberships = [ x for x in AuthMember.by_user_id(user_id=user_id) if x.role in roles ] group_ids = [x.group_id for x in memberships] # # q = model.Session.query(model.Member, model.Group) \ # .filter(model.Member.table_name == 'user') \ # .filter(model.Member.capacity.in_(roles)) \ # .filter(model.Member.table_id == user_id) \ # .filter(model.Member.state == 'active') \ # .join(model.Group) # # group_ids = set() # roles_that_cascade = \ # authz.check_config_permission('roles_that_cascade_to_sub_groups') # for member, group in q.all(): # if member.capacity in roles_that_cascade: # group_ids |= set([ # grp_tuple[0] for grp_tuple # in group.get_children_group_hierarchy(type='organization') # ]) # group_ids.add(group.id) # # if not group_ids: # return [] orgs_q = orgs_q.filter(model.Group.id.in_(group_ids)) orgs_list = model_dictize.group_list_dictize(orgs_q.all(), context) return orgs_list
def package_search(context, data_dict): schema = (context.get('schema') or logic.schema.default_package_search_schema()) data_dict, errors = _validate(data_dict, schema, context) # put the extras back into the data_dict so that the search can # report needless parameters data_dict.update(data_dict.get('__extras', {})) data_dict.pop('__extras', None) if errors: raise ValidationError(errors) model = context['model'] session = context['session'] user = context.get('user') _check_access('package_search', context, data_dict) # Move ext_ params to extras and remove them from the root of the search # params, so they don't cause and error data_dict['extras'] = data_dict.get('extras', {}) for key in [key for key in data_dict.keys() if key.startswith('ext_')]: data_dict['extras'][key] = data_dict.pop(key) # check if some extension needs to modify the search params for item in plugins.PluginImplementations(plugins.IPackageController): data_dict = item.before_search(data_dict) # the extension may have decided that it is not necessary to perform # the query abort = data_dict.get('abort_search', False) if data_dict.get('sort') in (None, 'rank'): data_dict['sort'] = 'score desc, metadata_modified desc' results = [] if not abort: if asbool(data_dict.get('use_default_schema')): data_source = 'data_dict' else: data_source = 'validated_data_dict' data_dict.pop('use_default_schema', None) # return a list of package ids data_dict['fl'] = 'id {0}'.format(data_source) # we should remove any mention of capacity from the fq and # instead set it to only retrieve public datasets fq = data_dict.get('fq', '') # Remove before these hit solr FIXME: whitelist instead include_private = asbool(data_dict.pop('include_private', False)) include_drafts = asbool(data_dict.pop('include_drafts', False)) capacity_fq = 'capacity:"public"' if include_private and authz.is_sysadmin(user): capacity_fq = None elif include_private and user: orgs = logic.get_action('organization_list_for_user')( {'user': user}, {'permission': 'read'}) if orgs: capacity_fq = '({0} OR owner_org:({1}))'.format( capacity_fq, ' OR '.join(org['id'] for org in orgs)) if include_drafts: capacity_fq = '({0} OR creator_user_id:({1}))'.format( capacity_fq, authz.get_user_id_for_username(user)) if capacity_fq: fq = ' '.join(p for p in fq.split() if 'capacity:' not in p) data_dict['fq'] = fq + ' ' + capacity_fq fq = data_dict.get('fq', '') if include_drafts: user_id = authz.get_user_id_for_username(user, allow_none=True) if authz.is_sysadmin(user): data_dict['fq'] = fq + ' +state:(active OR draft)' elif user_id: # Query to return all active datasets, and all draft datasets # for this user. data_dict['fq'] = fq + \ ' ((creator_user_id:{0} AND +state:(draft OR active))' \ ' OR state:active)'.format(user_id) elif not authz.is_sysadmin(user): data_dict['fq'] = fq + ' +state:active' # Pop these ones as Solr does not need them extras = data_dict.pop('extras', None) query = search.query_for(model.Package) query.run(data_dict) # Add them back so extensions can use them on after_search data_dict['extras'] = extras for package in query.results: # get the package object package_dict = package.get(data_source) ## use data in search index if there if package_dict: # the package_dict still needs translating when being viewed package_dict = json.loads(package_dict) if context.get('for_view'): for item in plugins.PluginImplementations( plugins.IPackageController): package_dict = item.before_view(package_dict) results.append(package_dict) else: log.error('No package_dict is coming from solr for package ' 'id %s', package['id']) count = query.count facets = query.facets else: count = 0 facets = {} results = [] search_results = { 'count': count, 'facets': facets, 'results': results, 'sort': data_dict['sort'] } # create a lookup table of group name to title for all the groups and # organizations in the current search's facets. group_names = [] for field_name in ('groups', 'organization'): group_names.extend(facets.get(field_name, {}).keys()) groups = (session.query(model.Group.name, model.Group.title) .filter(model.Group.name.in_(group_names)) .all() if group_names else []) group_titles_by_name = dict(groups) # Transform facets into a more useful data structure. restructured_facets = {} for key, value in facets.items(): restructured_facets[key] = { 'title': key, 'items': [] } for key_, value_ in value.items(): new_facet_dict = {} new_facet_dict['name'] = key_ if key in ('groups', 'organization'): display_name = group_titles_by_name.get(key_, key_) display_name = display_name if display_name and display_name.strip() else key_ new_facet_dict['display_name'] = display_name elif key == 'license_id': license = model.Package.get_license_register().get(key_) if license: new_facet_dict['display_name'] = license.title else: new_facet_dict['display_name'] = key_ else: new_facet_dict['display_name'] = key_ new_facet_dict['count'] = value_ restructured_facets[key]['items'].append(new_facet_dict) search_results['search_facets'] = restructured_facets # check if some extension needs to modify the search results for item in plugins.PluginImplementations(plugins.IPackageController): search_results = item.after_search(search_results, data_dict) # After extensions have had a chance to modify the facets, sort them by # display name. for facet in search_results['search_facets']: search_results['search_facets'][facet]['items'] = sorted( search_results['search_facets'][facet]['items'], key=lambda facet: facet['display_name'], reverse=True) return search_results