def new(self, data=None, errors=None, error_summary=None): '''GET to display a form for registering a new user. or POST the form data to actually do the user registration. ''' context = {'model': model, 'session': model.Session, 'user': c.user, 'auth_user_obj': c.userobj, 'schema': self._new_form_to_db_schema(), 'save': 'save' in request.params} try: check_access('user_create', context) except NotAuthorized: abort(403, _('Unauthorized to create a user')) if context['save'] and not data: return self._save_new(context) if c.user and not data and not authz.is_sysadmin(c.user): # #1799 Don't offer the registration form if already logged in return render('user/logout_first.html') data = data or {} errors = errors or {} error_summary = error_summary or {} vars = {'data': data, 'errors': errors, 'error_summary': error_summary} c.is_sysadmin = authz.is_sysadmin(c.user) c.form = render(self.new_user_form, extra_vars=vars) return render('user/new.html')
def ignore_not_package_admin(key, data, errors, context): '''Ignore if the user is not allowed to administer the package specified.''' model = context['model'] user = context.get('user') if 'ignore_auth' in context: return if user and authz.is_sysadmin(user): return authorized = False pkg = context.get('package') if pkg: try: logic.check_access('package_change_state',context) authorized = True except logic.NotAuthorized: authorized = False if (user and pkg and authorized): return # allow_state_change in the context will allow the state to be changed # FIXME is this the best way to cjeck for state only? if key == ('state',) and context.get('allow_state_change'): return data.pop(key)
def _setup_template_variables(self, context, data_dict): c.is_sysadmin = authz.is_sysadmin(c.user) try: user_dict = get_action('user_show')(context, data_dict) except NotFound: abort(404, _('User not found')) except NotAuthorized: abort(401, _('Not authorized to see this page')) c.user_dict = user_dict lang = get_lang()[0] # MULTILANG - Localizing Datasets names and descriptions in search list for item in c.user_dict.get('datasets'): log.info(':::::::::::: Retrieving the corresponding localized title and abstract :::::::::::::::') q_results = model.Session.query(PackageMultilang).filter(PackageMultilang.package_id == item.get('id'), PackageMultilang.lang == lang).all() if q_results: for result in q_results: item[result.field] = result.text c.is_myself = user_dict['name'] == c.user c.about_formatted = h.render_markdown(user_dict['about'])
def protect_portal_release_date(key, data, errors, context): """ Ensure the portal_release_date is not changed by an unauthorized user. """ if is_sysadmin(context['user']): return original = '' package = context.get('package') if package: original = package.extras.get('portal_release_date', '') value = data.get(key, '') if original == value: return user = context['user'] user = model.User.get(user) if may_publish_datasets(user): return if not value: # silently replace with the old value when none is sent data[key] = original return errors[key].append("Cannot change value of key from '%s' to '%s'. " 'This key is read-only' % (original, value)) raise StopOnError
def request_account(self, data=None, errors=None, error_summary=None): '''GET to display a form for requesting a user account or POST the form data to submit the request. ''' context = { 'model': model, 'session': model.Session, 'user': c.user or c.author, # why? #'user': model.Session.query(model.User).filter_by(sysadmin=True).first().name, 'auth_user_obj': c.userobj, 'schema': self._new_form_to_db_schema(), 'save': 'save' in request.params } if context['save'] and not data: return self._save_new_pending(context) if c.user and not data: # Don't offer the registration form if already logged in return render('user/logout_first.html') data = data or {} errors = errors or {} error_summary = error_summary or {} organizations = logic.get_action('organization_list')({}, {}) organization = [] for org in organizations: organization.append(logic.get_action('organization_show')({},{'id': org})) vars = {'data': data, 'errors': errors, 'error_summary': error_summary, 'organization': organization} c.is_sysadmin = authz.is_sysadmin(c.user) c.form = render(self.new_user_form, extra_vars=vars) return render('user/new.html')
def edit(self, id=None, data=None, errors=None, error_summary=None): context = {'save': 'save' in request.params, 'schema': self._edit_form_to_db_schema(), 'model': model, 'session': model.Session, 'user': c.user, 'auth_user_obj': c.userobj } if id is None: if c.userobj: id = c.userobj.id else: abort(400, _('No user specified')) data_dict = {'id': id} try: check_access('user_update', context, data_dict) except NotAuthorized: abort(403, _('Unauthorized to edit a user.')) if (context['save']) and not data: return self._save_edit(id, context) try: old_data = get_action('user_show')(context, data_dict) schema = self._db_to_edit_form_schema() if schema: old_data, errors = \ dictization_functions.validate(old_data, schema, context) c.display_name = old_data.get('display_name') c.user_name = old_data.get('name') data = data or old_data except NotAuthorized: abort(403, _('Unauthorized to edit user %s') % '') except NotFound: abort(404, _('User not found')) user_obj = context.get('user_obj') if not (authz.is_sysadmin(c.user) or c.user == user_obj.name): abort(403, _('User %s not authorized to edit %s') % (str(c.user), id)) errors = errors or {} vars = {'data': data, 'errors': errors, 'error_summary': error_summary} self._setup_template_variables({'model': model, 'session': model.Session, 'user': c.user}, data_dict) c.is_myself = True c.show_email_notifications = asbool( config.get('ckan.activity_streams_email_notifications')) c.form = render(self.edit_user_form, extra_vars=vars) return render('user/edit.html')
def new(self, data=None, errors=None, error_summary=None): """GET to display a form for registering a new user. or POST the form data to actually do the user registration. """ context = { "model": model, "session": model.Session, "user": c.user or c.author, "auth_user_obj": c.userobj, "schema": self._new_form_to_db_schema(), "save": "save" in request.params, } try: check_access("user_create", context) except NotAuthorized: abort(401, _("Unauthorized to create a user")) if context["save"] and not data: return self._save_new(context) if c.user and not data: # #1799 Don't offer the registration form if already logged in return render("user/logout_first.html") data = data or {} errors = errors or {} error_summary = error_summary or {} vars = {"data": data, "errors": errors, "error_summary": error_summary} c.is_sysadmin = authz.is_sysadmin(c.user) c.form = render(self.new_user_form, extra_vars=vars) return render("user/new.html")
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 member_requests_list(context, data_dict): ''' Organization admins/editors will see a list of member requests to be approved. :param group: name of the group (optional) :type group: string ''' logic.check_access('member_requests_list', context, data_dict) user = context.get('user', None) user_object = model.User.get(user) is_sysadmin = authz.is_sysadmin(user) # ALL members with pending state only query = model.Session.query(model.Member).filter( model.Member.table_name == "user").filter(model.Member.state == 'pending') if not is_sysadmin: admin_in_groups = 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 == user_object.id) if admin_in_groups.count() <= 0: return [] # members requests for this organization query = query.filter(model.Member.group_id.in_( admin_in_groups.values(model.Member.group_id))) group = data_dict.get('group', None) if group: group_object = model.Group.get(group) if group_object: query = query.filter(model.Member.group_id == group_object.id) members = query.all() return _member_list_dictize(members, context)
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 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 edit(self, id=None, data=None, errors=None, error_summary=None): context = { "save": "save" in request.params, "schema": self._edit_form_to_db_schema(), "model": model, "session": model.Session, "user": c.user, "auth_user_obj": c.userobj, } if id is None: if c.userobj: id = c.userobj.id else: abort(400, _("No user specified")) data_dict = {"id": id} try: check_access("user_update", context, data_dict) except NotAuthorized: abort(401, _("Unauthorized to edit a user.")) if (context["save"]) and not data: return self._save_edit(id, context) try: old_data = get_action("user_show")(context, data_dict) schema = self._db_to_edit_form_schema() if schema: old_data, errors = dictization_functions.validate(old_data, schema, context) c.display_name = old_data.get("display_name") c.user_name = old_data.get("name") data = data or old_data except NotAuthorized: abort(401, _("Unauthorized to edit user %s") % "") except NotFound: abort(404, _("User not found")) user_obj = context.get("user_obj") if not (authz.is_sysadmin(c.user) or c.user == user_obj.name): abort(401, _("User %s not authorized to edit %s") % (str(c.user), id)) errors = errors or {} vars = {"data": data, "errors": errors, "error_summary": error_summary} self._setup_template_variables( {"model": model, "session": model.Session, "user": c.user or c.author}, data_dict ) c.is_myself = True c.show_email_notifications = h.asbool(config.get("ckan.activity_streams_email_notifications")) c.form = render(self.edit_user_form, extra_vars=vars) return render("user/edit.html")
def get(self, data=None, errors=None, error_summary=None): self._prepare() if g.user and not data and not authz.is_sysadmin(g.user): # #1799 Don't offer the registration form if already logged in return base.render(u'user/logout_first.html', {}) form_vars = { u'data': data or {}, u'errors': errors or {}, u'error_summary': error_summary or {} } extra_vars = { u'is_sysadmin': authz.is_sysadmin(g.user), u'form': base.render(new_user_form, form_vars) } return base.render(u'user/new.html', extra_vars)
def ignore_not_sysadmin(key, data, errors, context): '''Ignore the field if user not sysadmin or ignore_auth in context.''' user = context.get('user') ignore_auth = context.get('ignore_auth') if ignore_auth or (user and authz.is_sysadmin(user)): return data.pop(key)
def register(self, data=None, errors=None, error_summary=None): '''GET to display a form for registering a new user. or POST the form data to actually do the user registration. The bulk of this code is pulled directly from ckan/controlllers/user.py ''' context = {'model': model, 'session': model.Session, 'user': c.user or c.author, 'schema': schema.user_new_form_schema(), 'save': 'save' in request.params} try: check_access('user_create', context) except NotAuthorized: abort(401, _('Unauthorized to create a user')) if context['save'] and not data: try: return self._save_new(context) except HTTPFound: # redirected after successful user create notify_ckan_user_create( email=request.params.get('email', ''), fullname=request.params.get('fullname', ''), username=request.params.get('name', ''), phoneno=request.params.get('phoneno', ''), dept=request.params.get('department', '')) notice_no_access() raise if c.user and not data and not is_sysadmin(c.user): # #1799 Don't offer the registration form if already logged in return render('user/logout_first.html') data = data or {} errors = errors or {} error_summary = error_summary or {} d = {'data': data, 'errors': errors, 'error_summary': error_summary} c.is_sysadmin = is_sysadmin(c.user) c.form = render('user/new_user_form.html', extra_vars=d) return render('user/new.html')
def empty_if_not_sysadmin(key, data, errors, context): '''Only sysadmins may pass this value''' from ckan.lib.navl.validators import empty user = context.get('user') ignore_auth = context.get('ignore_auth') if ignore_auth or (user and authz.is_sysadmin(user)): return empty(key, data, errors, context)
def datarequest_create(context, data_dict): ''' Action to create a new dara request. The function checks the access rights of the user before creating the data request. If the user is not allowed a NotAuthorized exception will be risen. In addition, you should note that the parameters will be checked and an exception (ValidationError) will be risen if some of these parameters are not valid. :param title: The title of the data request :type title: string :param description: A brief description for your data request :type description: string :param organiztion_id: If you want to create the data request in a specific organization. :type organization_id: string :returns: A dict with the data request (id, user_id, title, description, organization_id, open_time, accepted_dataset, close_time, closed) :rtype: dict ''' model = context['model'] session = context['session'] # Init the data base db.init_db(model) # Check access tk.check_access(constants.DATAREQUEST_CREATE, context, data_dict) # Validate data validator.validate_datarequest(context, data_dict) # Store the data data_req = db.DataRequest() _undictize_datarequest_basic(data_req, data_dict) data_req.user_id = context['auth_user_obj'].id if context['auth_user_obj'] else 'anonymous' data_req.open_time = datetime.datetime.now() data_req.visibility = constants.DataRequestState.visible.value context['ignore_auth'] = config.get('ckan.datarequests.ignore_auth', False) user = context['user'] if context['ignore_auth'] == False and not authz.is_sysadmin(user): data_req.visibility = constants.DataRequestState.hidden.value session.add(data_req) session.commit() return _dictize_datarequest(data_req)
def _guess_package_type(self, expecting_name=False): # this is a bit unortodox, but this method allows us to conveniently # alter the search method without much code duplication. if not is_sysadmin(c.user): abort(401, _('Not authorized to see this page')) # always set ready_to_publish to true for the publishing interface request.GET['ready_to_publish'] = u'true' # This MUST be None, otherwise the default filtering will apply and # restrict to just dataset_type=dataset. return None
def _setup_template_variables(self, context, data_dict): c.is_sysadmin = authz.is_sysadmin(c.user) try: user_dict = get_action('user_show')(context, data_dict) except NotFound: abort(404, _('User not found')) except NotAuthorized: abort(403, _('Not authorized to see this page')) c.user_dict = user_dict c.is_myself = user_dict['name'] == c.user c.about_formatted = h.render_markdown(user_dict['about'])
def _setup_template_variables(self, context, data_dict): c.is_sysadmin = authz.is_sysadmin(c.user) try: user_dict = get_action("user_show")(context, data_dict) except NotFound: abort(404, _("User not found")) except NotAuthorized: abort(401, _("Not authorized to see this page")) c.user_dict = user_dict c.is_myself = user_dict["name"] == c.user c.about_formatted = h.render_markdown(user_dict["about"])
def _setup_template_variables(self, context, data_dict): c.is_sysadmin = authz.is_sysadmin(c.user) try: user_dict = get_action('user_show')(context, data_dict) except NotFound: h.flash_error(_('Not authorized to see this page')) h.redirect_to(controller='user', action='login') except NotAuthorized: abort(403, _('Not authorized to see this page')) c.user_dict = user_dict c.is_myself = user_dict['name'] == c.user c.about_formatted = h.render_markdown(user_dict['about'])
def iati_publisher_state_validator(key, data, errors, context): user = context.get('user') if 'ignore_auth' in context: return if user and new_authz.is_sysadmin(user): return # If the user is not a sysadmin but we are creating the publisher, # we need to keep the state = pending value, otherwise ignore it. if not context.get('__iati_state_pending'): data.pop(key)
def user_password_not_empty(key, data, errors, context): '''Only check if password is present if the user is created via action API. If not, user_both_passwords_entered will handle the validation''' # sysadmin may provide password_hash directly for importing users if (data.get(('password_hash', ), missing) is not missing and authz.is_sysadmin(context.get('user'))): return if not ('password1', ) in data and not ('password2', ) in data: password = data.get(('password', ), None) if not password: errors[key].append(_('Missing value'))
def organization_form_read_only(data): """ data contains most of the publisher data. However, for the first time it contains state of the dataset but if any validation error in the form, then data doest contain state. Hence, organization_show is necessary which is a quite an expensive process for the validation. """ sysadmin = authz.is_sysadmin(c.user) attrs = {} if not sysadmin and data and data.get('state', '') == 'active': attrs = {'readonly': "readonly"} return attrs
def _guess_package_type(self, expecting_name=False): # this is a bit unortodox, but this method allows us to conveniently # alter the search method without much code duplication. if not is_sysadmin(c.user): abort(401, _('Not authorized to see this page')) # always set ready_to_publish to true for the publishing interface request.GET['ready_to_publish'] = u'true' request.GET['imso_approval'] = u'true' # This MUST be None, otherwise the default filtering will apply and # restrict to just dataset_type=dataset. return None
def new(self, data=None, errors=None, error_summary=None): '''GET to display a form for registering a new user. or POST the form data to actually do the user registration. ''' context = { 'model': model, 'session': model.Session, 'user': c.user, 'auth_user_obj': c.userobj, 'schema': self._new_form_to_db_schema(), 'save': 'save' in request.params } try: check_access('user_create', context) except NotAuthorized: abort(403, _('Unauthorized to create a user')) if context['save'] and not data: return self._save_new(context) if c.user and not data and not authz.is_sysadmin(c.user): # #1799 Don't offer the registration form if already logged in return render('user/logout_first.html') data = data or {} errors = errors or {} error_summary = error_summary or {} vars = { 'data': data, 'errors': errors, 'error_summary': error_summary, 'origin': origin, 'countries': allCountries, 'occupations': occupations } c.is_sysadmin = authz.is_sysadmin(c.user) c.form = render(self.new_user_form, extra_vars=vars) return render('user/new.html')
def get(self, data: Optional[dict[str, Any]] = None, errors: Optional[dict[str, Any]] = None, error_summary: Optional[dict[str, Any]] = None) -> str: self._prepare() user = current_user.name if user and not data and not authz.is_sysadmin(user): # #1799 Don't offer the registration form if already logged in return base.render(u'user/logout_first.html', {}) form_vars = { u'data': data or {}, u'errors': errors or {}, u'error_summary': error_summary or {} } extra_vars: dict[str, Any] = { u'is_sysadmin': authz.is_sysadmin(user), u'form': base.render(new_user_form, form_vars) } return base.render(u'user/new.html', extra_vars)
def user_password_not_empty(key, data, errors, context): '''Only check if password is present if the user is created via action API. If not, user_both_passwords_entered will handle the validation''' # sysadmin may provide password_hash directly for importing users if (data.get(('password_hash',), missing) is not missing and authz.is_sysadmin(context.get('user'))): return if not ('password1',) in data and not ('password2',) in data: password = data.get(('password',),None) if not password: errors[key].append(_('Missing value'))
def check_access_api_action(api_user, api_action): ''' Check an api_action against a list of restricted API actions :param api_user: :param api_action: :return: False if api_action is restricted and no user, or user not sysadmin, else True ''' # @TODO: Improve this to handle wildcards such as `harvest_source*` restricted_api_actions = config.get('ckan.restricted.api_actions', []) if api_action in restricted_api_actions: if not api_user or not authz.is_sysadmin(api_user.name): return False return True
def _setup_template_variables(self, context, data_dict): c.is_sysadmin = authz.is_sysadmin(c.user) try: # calling adapted user_show instead of CKAN's user_show user_dict = _user_show(context, data_dict) except NotFound: abort(404, _('User not found')) except NotAuthorized: abort(403, _('Not authorized to see this page')) c.user_dict = user_dict c.is_myself = user_dict['name'] == c.user c.about_formatted = h.render_markdown(user_dict['about'])
def post(self): context = self._prepare() try: data_dict = logic.clean_dict( dictization_functions.unflatten( logic.tuplize_dict(logic.parse_params(request.form)))) data_dict.update(logic.clean_dict( dictization_functions.unflatten( logic.tuplize_dict(logic.parse_params(request.files))) )) except dictization_functions.DataError: base.abort(400, _(u'Integrity Error')) context[u'message'] = data_dict.get(u'log_message', u'') try: captcha.check_recaptcha(request) except captcha.CaptchaError: error_msg = _(u'Bad Captcha. Please try again.') h.flash_error(error_msg) return self.get(data_dict) try: logic.get_action(u'user_create')(context, data_dict) except logic.NotAuthorized: base.abort(403, _(u'Unauthorized to create user %s') % u'') except logic.NotFound: base.abort(404, _(u'User not found')) except logic.ValidationError as e: errors = e.error_dict error_summary = e.error_summary return self.get(data_dict, errors, error_summary) if g.user: # #1799 User has managed to register whilst logged in - warn user # they are not re-logged in as new user. h.flash_success( _(u'User "%s" is now registered but you are still ' u'logged in as "%s" from before') % (data_dict[u'name'], g.user)) if authz.is_sysadmin(g.user): # the sysadmin created a new user. We redirect him to the # activity page for the newly created user return h.redirect_to(u'user.activity', id=data_dict[u'name']) else: return base.render(u'user/logout_first.html') # log the user in programatically resp = h.redirect_to(u'user.me') set_repoze_user(data_dict[u'name'], resp) return resp
def user_dictize( user, context, include_password_hash=False, include_plugin_extras=False): if context.get('with_capacity'): user, capacity = user result_dict = d.table_dictize(user, context, capacity=capacity) else: result_dict = d.table_dictize(user, context) password_hash = result_dict.pop('password') del result_dict['reset_key'] result_dict['display_name'] = user.display_name result_dict['email_hash'] = user.email_hash result_dict['number_created_packages'] = user.number_created_packages( include_private_and_draft=context.get( 'count_private_and_draft_datasets', False)) requester = context.get('user') reset_key = result_dict.pop('reset_key', None) apikey = result_dict.pop('apikey', None) email = result_dict.pop('email', None) plugin_extras = result_dict.pop('plugin_extras', None) if context.get('keep_email', False): result_dict['email'] = email if context.get('keep_apikey', False): result_dict['apikey'] = apikey if requester == user.name: result_dict['apikey'] = apikey result_dict['email'] = email if authz.is_sysadmin(requester): result_dict['apikey'] = apikey result_dict['email'] = email if include_password_hash: result_dict['password_hash'] = password_hash if include_plugin_extras: result_dict['plugin_extras'] = copy.deepcopy( plugin_extras) if plugin_extras else plugin_extras model = context['model'] session = model.Session return result_dict
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 user_dictize(user, context, include_password_hash=False): if context.get('with_capacity'): user, capacity = user result_dict = d.table_dictize(user, context, capacity=capacity) else: result_dict = d.table_dictize(user, context) password_hash = result_dict.pop('password') del result_dict['reset_key'] result_dict['display_name'] = user.display_name result_dict['email_hash'] = user.email_hash result_dict['number_of_edits'] = user.number_of_edits() result_dict['number_created_packages'] = user.number_created_packages( include_private_and_draft=context.get( 'count_private_and_draft_datasets', False)) requester = context.get('user') reset_key = result_dict.pop('reset_key', None) apikey = result_dict.pop('apikey', None) email = result_dict.pop('email', None) if context.get('keep_email', False): result_dict['email'] = email if context.get('keep_apikey', False): result_dict['apikey'] = apikey if requester == user.name: result_dict['apikey'] = apikey result_dict['email'] = email if authz.is_sysadmin(requester): result_dict['apikey'] = apikey result_dict['email'] = email if include_password_hash: result_dict['password_hash'] = password_hash model = context['model'] session = model.Session if context.get('with_related'): related_items = session.query(model.Related).\ filter(model.Related.owner_id==user.id).all() result_dict['related_items'] = related_list_dictize(related_items, context) return result_dict
def edit(self, id=None, data=None, errors=None, error_summary=None): context = { 'save': 'save' in request.params, 'schema': self._edit_form_to_db_schema(), 'model': model, 'session': model.Session, 'user': c.user, 'auth_user_obj': c.userobj } if id is None: if c.userobj: id = c.userobj.id else: abort(400, _('No user specified')) data_dict = {'id': id} try: check_access('user_update', context, data_dict) except NotAuthorized: abort(403, _('Unauthorized to edit a user.')) if context['save'] and not data and request.method == 'POST': return self._save_edit(id, context) try: old_data = get_action('user_show')(context, data_dict) schema = self._db_to_edit_form_schema() if schema: old_data, errors = \ dictization_functions.validate(old_data, schema, context) c.display_name = old_data.get('display_name') c.user_name = old_data.get('name') data = data or old_data except NotAuthorized: abort(403, _('Unauthorized to edit user %s') % '') except NotFound: abort(404, _('User not found')) user_obj = context.get('user_obj') if not (authz.is_sysadmin(c.user) or c.user == user_obj.name): abort(403, _('User %s not authorized to edit %s') % (str(c.user), id)) errors = errors or {} vars = {'data': data, 'errors': errors, 'error_summary': error_summary} self._setup_template_variables( { 'model': model, 'session': model.Session, 'user': c.user }, data_dict) c.is_myself = True c.show_email_notifications = asbool( config.get('ckan.activity_streams_email_notifications')) c.form = render(self.edit_user_form, extra_vars=vars) return render('user/edit.html')
def user_dictize(user, context, include_password_hash=False): if context.get('with_capacity'): user, capacity = user result_dict = d.table_dictize(user, context, capacity=capacity) else: result_dict = d.table_dictize(user, context) password_hash = result_dict.pop('password') del result_dict['reset_key'] result_dict['display_name'] = user.display_name result_dict['email_hash'] = user.email_hash result_dict['number_of_edits'] = user.number_of_edits() result_dict['number_created_packages'] = user.number_created_packages( include_private_and_draft=context.get( 'count_private_and_draft_datasets', False)) requester = context.get('user') reset_key = result_dict.pop('reset_key', None) apikey = result_dict.pop('apikey', None) email = result_dict.pop('email', None) if context.get('keep_email', False): result_dict['email'] = email if context.get('keep_apikey', False): result_dict['apikey'] = apikey if requester == user.name: result_dict['apikey'] = apikey result_dict['email'] = email if authz.is_sysadmin(requester): result_dict['apikey'] = apikey result_dict['email'] = email if include_password_hash: result_dict['password_hash'] = password_hash model = context['model'] session = model.Session if context.get('with_related'): related_items = session.query(model.Related).\ filter(model.Related.owner_id==user.id).all() result_dict['related_items'] = related_list_dictize( related_items, context) return result_dict
def _check_access_to_change_ids(key, data, group, user): if isinstance(key, tuple): key_comp = key[0] if key_comp =='publisher_iati_id': val = group.extras.get('publisher_iati_id', '') elif key_comp == 'name': val = group.name if val and val != data.get(key) and group.state == 'active': if not new_authz.is_sysadmin(user): return False return True
def check_access_ui_path(repoze_who_identity, username, ui_path): ''' Check a UI path (URI) against a list of restricted paths set in the CKAN `.ini` file :param repoze_who_identity: :param username: :param ui_path: :return: ''' # @TODO: Improve this to handle wildcards such as /user/salsa (without restricting /user/XYZ/edit when required) restricted_ui_paths = config.get('ckan.restricted.ui_paths', []).split() if ui_path in restricted_ui_paths: if not repoze_who_identity or not username or not authz.is_sysadmin(username): return False return True
def dataset_license_id(key, data, errors, context): """Restrict to licenses.json (except sysadmins)""" user = context.get('user') ignore_auth = context.get('ignore_auth') if ignore_auth or (user and authz.is_sysadmin(user)): return value = data[key] register = model.Package.get_license_register() sorted_licenses = sorted(register.values(), key=lambda x: x.title) license_ids = [ll.id for ll in sorted_licenses if ll.id != "none"] if value not in license_ids: raise toolkit.Invalid( "Please choose a license_id: {}".format(license_ids))
def attr_map_edit(self, id, attr_map_id, data=None, errors=None, error_summary=None): context = { 'model': model, 'session': model.Session, 'user': tk.c.user, 'save': 'save' in tk.request.params } if context['save'] and not data and tk.request.method == 'POST': return self._save_attr_map_edit(id, attr_map_id, context) try: tk.check_access('metadata_json_attr_map_update', context) except tk.NotAuthorized: tk.abort(403, tk._('Not authorized to update attribute mappings')) try: old_data = tk.get_action('metadata_json_attr_map_show')( context, { 'id': attr_map_id }) data = data or old_data except (tk.ObjectNotFound, tk.NotAuthorized): tk.abort(404, tk._('Attribute map not found')) errors = errors or {} error_summary = error_summary or {} vars = { 'data': data, 'errors': errors, 'error_summary': error_summary, 'action': 'edit', 'record_attr_list': self._attr_map_record_attr_list(), 'is_elasticsearch_enabled': self._is_elasticsearch_enabled() } tk.c.metadata_standard = tk.get_action('metadata_standard_show')( context, { 'id': id }) tk.c.is_sysadmin = authz.is_sysadmin(tk.c.user) tk.c.form = tk.render('metadata_standard/attr_map_form.html', extra_vars=vars) return tk.render('metadata_standard/attr_map_edit.html', extra_vars=vars)
def ogdch_admin_capacity(): """tests whether the current user is a sysadmin or an organization admin """ if authz.is_sysadmin(c.user): return True context = {"user": c.user, "auth_user_obj": c.userobj} roles_for_user = tk.get_action("organization_list_for_user")(context, { "id": c.user }) capacities = [role.get("capacity") for role in roles_for_user] if CAPACITY_ADMIN in capacities: return True return False
def policy(self, policy_id): if not authz.is_sysadmin(c.user): abort(403, _('Unauthorized')) c.policy = GDPRPolicy.get(id=policy_id) accepted_policy = GDPRAccept.filter(policy_id=c.policy.id) c.accepting_users = [] for policy in accepted_policy: c.accepting_users.append(User.get(policy.user_id)) c.not_accepting_users = [ item for item in User.all() if item not in c.accepting_users ] return toolkit.render('gdpr/policy.html')
def _save_new(self, context): came_from = request.params.get('came_from', '') sig = request.params.get('sig', '') redirect_url = came_from + '&sig=' + sig if came_from != '' else '' redirect_url = str(redirect_url) #to deal with Unicode objects try: data_dict = logic.clean_dict( unflatten( logic.tuplize_dict(logic.parse_params(request.params)))) context['message'] = data_dict.get('log_message', '') captcha.check_recaptcha(request) user = get_action('user_create')(context, data_dict) except NotAuthorized: abort(403, _('Unauthorized to create user %s') % '') except NotFound as e: abort(404, _('User not found')) except DataError: abort(400, _(u'Integrity Error')) except captcha.CaptchaError: error_msg = _(u'Bad Captcha. Please try again.') h.flash_error(error_msg) return self.new(data_dict) except ValidationError as e: errors = e.error_dict error_summary = e.error_summary return self.new(data_dict, errors, error_summary) if not c.user: # log the user in programatically set_repoze_user(data_dict['name']) if redirect_url == '': h.redirect_to(controller='user', action='me') else: log.error("\n\n Redirect URL: %s\n\n" % redirect_url) h.redirect_to(redirect_url) else: # #1799 User has managed to register whilst logged in - warn user # they are not re-logged in as new user. h.flash_success( _('User "%s" is now registered but you are still ' 'logged in as "%s" from before') % (data_dict['name'], c.user)) if authz.is_sysadmin(c.user): # the sysadmin created a new user. We redirect him to the # activity page for the newly created user h.redirect_to(controller='user', action='activity', id=data_dict['name']) else: return render('user/logout_first.html')
def gdpr(self): if not authz.is_sysadmin(c.user): abort(403, _('Unauthorized')) gdpr = GDPR.get() if request.method == 'GET': c.tos = '' c.policies = {} if gdpr is not None: c.tos = gdpr.tos c.policies = GDPRPolicy.filter(gdpr_id=gdpr.id).order_by( GDPRPolicy.id) return toolkit.render('gdpr/gdpr.html') if request.method == 'POST': log.debug(request.POST) if gdpr is None: gdpr = GDPR.create(tos=request.POST.get('tos')) gdpr = GDPR.get() else: gdpr.tos = request.POST.get('tos') # Create new policies log.debug('Creating new policies') for key in request.POST.iterkeys(): if key.startswith('policy-'): required = False if 'required-{}'.format(key) in request.POST: required = True GDPRPolicy.create(content=request.POST.get(key), required=required, gdpr_id=gdpr.id) # Update existing policies for key in request.POST.iterkeys(): if not key.startswith(('policy-', 'required-', 'tos')): required = False if 'required-{}'.format(key) in request.POST: required = True policy = GDPRPolicy.get(id=key) policy.content = request.POST.get(key) policy.required = required policy.save() model.repo.commit() model.repo.commit() return redirect('/gdpr')
def member_requests_mylist(context, data_dict): ''' Users wil see a list of her member requests ''' logic.check_access('member_requests_mylist', context, data_dict) user = context.get('user', None) if authz.is_sysadmin(user): return [] user_object = model.User.get(user) # Return current state for memberships for all organizations for the user # in context. (last modified date) membership_requests = model.Session.query(model.Member).filter( model.Member.table_id == user_object.id).all() return _membeship_request_list_dictize(membership_requests, context)
def new(self, data=None, errors=None, error_summary=None): '''GET to display a form for registering a new user. or POST the form data to actually do the user registration. ''' context = { 'model': model, 'session': model.Session, 'user': c.user, 'auth_user_obj': c.userobj, 'schema': self._new_form_to_db_schema(), 'save': 'save' in request.params } try: check_access('user_create', context) except NotAuthorized: h.redirect_to(u'user.login') if context['save'] and not data and request.method == 'POST': return self._save_new(context) if c.user and not data and not authz.is_sysadmin(c.user): # #1799 Don't offer the registration form if already logged in return render('user/logout_first.html') form_vars = { u'data': data or {}, u'errors': errors or {}, u'error_summary': error_summary or {} } extra_vars = { u'is_sysadmin': authz.is_sysadmin(c.user), u'form': render(self.new_user_form, form_vars) } return render(u'user/new.html', extra_vars)
def group_tree_filtered(context, data_dict): currentuser = context['user'] sysadmin = authz.is_sysadmin(currentuser) model = context['model'] group_type = data_dict.get('type', 'group') group_counts = model_dictize.get_group_dataset_counts()['owner_org'] filtered_groups = [] for group in model.Group.get_top_level_groups(type=group_type): branch = _group_tree_branch(group, type=group_type, group_counts=None if sysadmin else group_counts) if len(branch['children']) > 0 or branch['id'] in group_counts or sysadmin: filtered_groups.append(branch) return filtered_groups
def type_redirect(self, resource_name): orgs = h.organizations_available('read') if not orgs: abort(404, _('No organizations found')) try: chromo = get_chromo(resource_name) except RecombinantException: abort(404, _('Recombinant resource_name not found')) # custom business logic if is_sysadmin(c.user): return redirect(h.url_for('recombinant_resource', resource_name=resource_name, owner_org='tbs-sct')) return redirect(h.url_for('recombinant_resource', resource_name=resource_name, owner_org=orgs[0]['name']))
def get_user_email(context, data_dict): ''' Returns the user names and emails of all the users ''' if not authz.is_sysadmin(toolkit.c.user): toolkit.abort(403, _('You are not authorized to access this list')) user_list = toolkit.get_action('user_list')(context, data_dict) user_name_email = [] for user in user_list: email = user['email'] user_name = user['display_name'] user_name_email.append({'user_name':user_name, 'email_address':email}) return user_name_email
def register(self, data=None, errors=None, error_summary=None): '''GET to display a form for registering a new user. or POST the form data to actually do the user registration. The bulk of this code is pulled directly from ckan/controlllers/user.py ''' context = { 'model': model, 'session': model.Session, 'user': c.user or c.author, 'schema': schema.user_new_form_schema(), 'save': 'save' in request.params } try: check_access('user_create', context) except NotAuthorized: abort(401, _('Unauthorized to create a user')) if context['save'] and not data: try: return self._save_new(context) except HTTPFound: # redirected after successful user create notify_ckan_user_create( email=request.params.get('email', ''), fullname=request.params.get('fullname', ''), username=request.params.get('name', ''), phoneno=request.params.get('phoneno', ''), dept=request.params.get('department', '')) notice_no_access() raise if c.user and not data: # #1799 Don't offer the registration form if already logged in return render('user/logout_first.html') data = data or {} errors = errors or {} error_summary = error_summary or {} d = {'data': data, 'errors': errors, 'error_summary': error_summary} c.is_sysadmin = is_sysadmin(c.user) c.form = render('user/new_user_form.html', extra_vars=d) return render('user/new.html')
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 post(self): context = self._prepare() try: data_dict = logic.clean_dict( dictization_functions.unflatten( logic.tuplize_dict(logic.parse_params(request.form)))) except dictization_functions.DataError: base.abort(400, _(u'Integrity Error')) context[u'message'] = data_dict.get(u'log_message', u'') try: captcha.check_recaptcha(request) except captcha.CaptchaError: error_msg = _(u'Bad Captcha. Please try again.') h.flash_error(error_msg) return self.get(data_dict) try: logic.get_action(u'user_create')(context, data_dict) except logic.NotAuthorized: base.abort(403, _(u'Unauthorized to create user %s') % u'') except logic.NotFound: base.abort(404, _(u'User not found')) except logic.ValidationError as e: errors = e.error_dict error_summary = e.error_summary return self.get(data_dict, errors, error_summary) if g.user: # #1799 User has managed to register whilst logged in - warn user # they are not re-logged in as new user. h.flash_success( _(u'User "%s" is now registered but you are still ' u'logged in as "%s" from before') % (data_dict[u'name'], g.user)) if authz.is_sysadmin(g.user): # the sysadmin created a new user. We redirect him to the # activity page for the newly created user return h.redirect_to(u'user.activity', id=data_dict[u'name']) else: return base.render(u'user/logout_first.html') # log the user in programatically resp = h.redirect_to(u'user.me') set_repoze_user(data_dict[u'name'], resp) return resp
def _setup_template_variables(self, context, data_dict): """ Sets up template variables. If the user is deleted, throws a 404 unless the user is logged in as sysadmin. """ c.is_sysadmin = new_authz.is_sysadmin(c.user) try: user_dict = get_action('user_show')(context, data_dict) except NotFound: abort(404, _('User not found')) except NotAuthorized: abort(401, _('Not authorized to see this page')) if user_dict['state'] == 'deleted' and not c.is_sysadmin: abort(404, _('User not found')) c.user_dict = user_dict c.is_myself = user_dict['name'] == c.user c.about_formatted = h.render_markdown(user_dict['about'])
def _user_has_minumum_role(context): """ Determines whether the user has the minimum required role as specific in configuration. This is deliberately verbose. """ roles = ['editor', 'admin', 'sysadmin'] user = context['user'] userobj = model.User.get(user) # Do we have a configured minimum role, if not just say ok now. minimum_role = config.get('ckanext.webhooks.minimum_auth', '').lower() if not minimum_role or minimum_role.lower() == 'none': return {'success': True} # Validate that the config option is valid and refuse, if we added # the option we probably wanted it to be *something*. if not minimum_role in roles: log.warning("ckanext.webhooks.minimum_auth has an invalid option") return {'success': False} # Always let sysadmins do their thing. if authz.is_sysadmin(user): return {'success': True} # We let sysadmins in just not, so just refuse if we get here. if minimum_role == 'sysadmin': return {'success': False} # Determine if the user has the required role in any organization q = model.Session.query(model.Member) \ .filter(model.Member.table_name == 'user') \ .filter(model.Member.table_id == userobj.id) \ .filter(model.Member.state == 'active') roles_for_user = [m.capacity for m in q.all()] # If we want admins, let in anyone who has admin if minimum_role == 'admin': if 'admin' in roles_for_user: return {'success': True} # Only allow users who have editor if minimum_role == 'editor': if 'editor' in roles_for_user or 'admin' in roles_for_user: return {'success': True} return {'success': False}
def search(cls, querystr, sqlalchemy_query=None, user_name=None): '''Search name, fullname, email. ''' if sqlalchemy_query is None: query = meta.Session.query(cls) else: query = sqlalchemy_query qstr = '%' + querystr + '%' filters = [ cls.name.ilike(qstr), cls.fullname.ilike(qstr), ] # sysadmins can search on user emails import ckan.authz as authz if user_name and authz.is_sysadmin(user_name): filters.append(cls.email.ilike(qstr)) query = query.filter(or_(*filters)) return query
def _extra_template_variables(context, data_dict): is_sysadmin = authz.is_sysadmin(g.user) try: user_dict = logic.get_action(u'user_show')(context, data_dict) except logic.NotFound: h.flash_error(_(u'Not authorized to see this page')) return except logic.NotAuthorized: base.abort(403, _(u'Not authorized to see this page')) is_myself = user_dict[u'name'] == g.user about_formatted = h.render_markdown(user_dict[u'about']) extra = { u'is_sysadmin': is_sysadmin, u'user_dict': user_dict, u'is_myself': is_myself, u'about_formatted': about_formatted } return extra
def datastore_create_temp_user_table(context): ''' Create a table to pass the current username and sysadmin state to our triggers for marking modified rows ''' from ckanext.datastore.helpers import literal_string connection = context['connection'] username = context['user'] connection.execute(u''' CREATE TEMP TABLE datastore_user ( username text NOT NULL, sysadmin boolean NOT NULL ) ON COMMIT DROP; INSERT INTO datastore_user VALUES ( {username}, {sysadmin} ); '''.format( username=literal_string(username), sysadmin='TRUE' if is_sysadmin(username) else 'FALSE'))