def login(self): params = toolkit.request.params if 'id_token' in params: try: mail_verified = self.verify_email(params['id_token']) except GoogleAuthException, e: toolkit.abort(500) user_account = email_to_ckan_user(mail_verified) user_ckan = self.get_ckanuser(user_account) if not user_ckan: user_ckan = toolkit.get_action('user_create')( context={'ignore_auth': True}, data_dict={'email': mail_verified, 'name': user_account, 'password': self.get_ckanpasswd()}) pylons.session['ckanext-google-user'] = user_ckan['name'] pylons.session['ckanext-google-email'] = mail_verified #to revoke the Google token uncomment the code below #pylons.session['ckanext-google-accesstoken'] = params['token'] pylons.session.save()
def new(self, data=None, errors=None, error_summary=None): context = self._get_context() try: tk.check_access('oauth2provider_client_create', context) except tk.NotAuthorized: tk.abort(401, _('Unauthorized to create an oauth2 client')) if tk.request.method == 'POST': data = dict(tk.request.params) try: data['user_id'] = model.User.by_name(data['username']).id except AttributeError: data['user_id'] = None client = tk.get_action('oauth2provider_client_create')(context, data) return tk.redirect_to('oauth2provider_client_list') data = data or {} errors = errors or {} error_summary = error_summary or {} vars = {'data': data, 'errors': errors, 'error_summary': error_summary, 'action': 'new'} return tk.render('ckanext/oauth2provider/client/new.html', extra_vars=vars)
def edit(self, organization_name, inventory_entry_id, data=None, errors=None, error_summary=None): context = {'model': model, 'session': model.Session, 'user': c.user or c.author, 'organization_name': c.organization_name, 'save': 'save' in request.params, 'schema': default_inventory_entry_schema_create()} if context['save'] and not data: return self._save_edit(inventory_entry_id, context) try: old_data = get_action('inventory_entry_show')( context, {'id': inventory_entry_id}) data = data or old_data except NotFound: abort(404, _('Inventory Entry not found')) except NotAuthorized: abort(401, _('Unauthorized to read inventory entry')) data = data or {} errors = errors or {} error_summary = error_summary or {} vars = {'data': data, 'errors': errors, 'error_summary': error_summary, 'action': 'edit'} c.form = render('inventory/entry/inventory_entry_form.html', extra_vars=vars) return render('inventory/entry/edit.html')
def index(self): try: reports = t.get_action('report_list')({}, {}) except t.NotAuthorized: t.abort(401) return t.render('report/index.html', extra_vars={'reports': reports})
def __before__(self, action, **params): super(InventoryManageController, self).__before__(action, **params) context = {'user': c.user, 'auth_user_obj': c.userobj} try: check_access('user_show', context, {}) except NotAuthorized: abort(401, 'You need to have an account.')
def report_comment(self, dataset_id, issue_number, comment_id): dataset = self._before_dataset(dataset_id) if request.method == 'POST': if not c.user: msg = _('You must be logged in to report comments') toolkit.abort(401, msg) try: toolkit.get_action('issue_comment_report')( data_dict={ 'comment_id': comment_id, 'issue_number': issue_number, 'dataset_id': dataset_id } ) h.flash_success( _('Comment has been reported to an administrator') ) h.redirect_to('issues_show', dataset_id=dataset_id, issue_number=issue_number) except toolkit.ValidationError: toolkit.abort(404) except ReportAlreadyExists, e: h.flash_error(e.message) h.redirect_to('issues_show', dataset_id=dataset_id, issue_number=issue_number)
def delete(self, dataset_id, issue_number): dataset = self._before_dataset(dataset_id) if 'cancel' in request.params: h.redirect_to('issues_show', dataset_id=dataset_id, issue_number=issue_number) if request.method == 'POST': try: toolkit.get_action('issue_delete')( data_dict={'issue_number': issue_number, 'dataset_id': dataset_id} ) except toolkit.NotAuthorized: msg = _('Unauthorized to delete issue {0}'.format( issue_number)) toolkit.abort(401, msg) h.flash_notice( _('Issue {0} has been deleted.'.format(issue_number)) ) h.redirect_to('issues_dataset', dataset_id=dataset_id) else: return render('issues/confirm_delete.html', extra_vars={ 'issue_number': issue_number, 'pkg': dataset, })
def new(self, data=None, errors=None, error_summary=None): '''This is a modified version of the core user controller We have removed the lines redirecting the user the logout page if they are already logged in, this allows sysadmins to create users as we have disabled user registration unless they are sys admins''' context = {'model': model, 'session': model.Session, 'user': toolkit.c.user or toolkit.c.author, 'auth_user_obj': toolkit.c.userobj, 'schema': self._new_form_to_db_schema(), 'save': 'save' in toolkit.request.params} try: toolkit.check_access('user_create', context) except toolkit.NotAuthorized: toolkit.abort(401, toolkit._('Unauthorized to create a user')) if context['save'] and not data: return self._save_new(context) data = data or {} errors = errors or {} error_summary = error_summary or {} vars = {'data': data, 'errors': errors, 'error_summary': error_summary} toolkit.c.is_sysadmin = new_authz.is_sysadmin(toolkit.c.user) toolkit.c.form = toolkit.render(self.new_user_form, extra_vars=vars) return toolkit.render('user/new.html')
def read_catalog(self, _format=None): if not _format: _format = check_access_header() if not _format: return index_endpoint() _profiles = toolkit.request.params.get('profiles') if _profiles: _profiles = _profiles.split(',') data_dict = { 'page': toolkit.request.params.get('page'), 'modified_since': toolkit.request.params.get('modified_since'), 'q': toolkit.request.params.get('q'), 'fq': toolkit.request.params.get('fq'), 'format': _format, 'profiles': _profiles, } toolkit.response.headers.update( {'Content-type': CONTENT_TYPES[_format]}) try: return toolkit.get_action('dcat_catalog_show')({}, data_dict) except (toolkit.ValidationError, RDFProfileException) as e: toolkit.abort(409, str(e))
def report_view(self, id): """ """ page = int(tk.request.params.get('page', 0)) perpage = int(tk.request.params.get('perpage', 10)) report, results, total, show_org = self._report_view(id, page, perpage) tk.c.sub_title = _(report['name']) tk.c.total = total tk.c.page = page tk.c.perpage = perpage tk.c.start_record = (page * perpage) + 1 tk.c.end_record = min((page * perpage) + perpage, total) tk.c.lastpage = int(math.ceil(total / perpage)) tk.c.report = report if report['report_on'] == "activities": tk.c.activities = results elif report['report_on'] == "details": tk.c.users = results tk.c.show_org = show_org else: tk.abort(404, tk._('Report not found')) return render('vdojstats-report-view.html')
def dump(self, resource_id): data, errors = dict_fns.validate(dict(request.GET), dump_schema()) if errors: abort(400, u'\n'.join( u'{0}: {1}'.format(k, ' '.join(e)) for k, e in errors.items())) try: dump_to( resource_id, response, fmt=data['format'], offset=data['offset'], limit=data.get('limit'), options={u'bom': data['bom']}, sort=data['sort'], search_params={ k: v for k, v in data.items() if k in [ 'filters', 'q', 'distinct', 'plain', 'language', 'fields']}, ) except ObjectNotFound: abort(404, _('DataStore resource not found'))
def export(self): context = {'model': model, 'user': toolkit.c.user, 'auth_user_obj': toolkit.c.userobj} try: toolkit.check_access('export_csv', context, {}) except toolkit.NotAuthorized: toolkit.abort(401, toolkit._( 'Need to be organization administrator to export as CSV') ) columns = os.path.join(this_directory(), "columns.json") csv_table = export(columns) # export() returns user IDs not user names in the "Uploaded By" column # because that's all the dataset dicts that package_search() returns # contain. Convert these IDs to user names ourselves. convert_user_ids_to_user_names(csv_table) csv_string = convert_csv_table_to_csv_string(csv_table) toolkit.response.headers["Content-type"] = "text/csv" toolkit.response.headers["Content-disposition"] = ( "attachment; filename=export.csv") return csv_string
def review(self, id): """ sends review notification to all journal admins """ context = self._context() try: tk.check_access('package_update', context, {'id': id}) except tk.NotAuthorized: tk.abort(403, 'Unauthorized') c.pkg_dict = tk.get_action('package_show')(context, {'id': id}) # avoid multiple notifications (eg. when someone calls review directly) if c.pkg_dict.get('dara_edawax_review', 'false') == 'true': h.flash_error("Package has already been sent to review") redirect(id) user_name = tk.c.userobj.fullname or tk.c.userobj.email admins = get_group_or_org_admin_ids(c.pkg_dict['owner_org']) addresses = map(lambda admin_id: model.User.get(admin_id).email, admins) note = n.review(addresses, user_name, id) if note: c.pkg_dict['dara_edawax_review'] = 'true' tk.get_action('package_update')(context, c.pkg_dict) h.flash_success('Notification to Editors sent.') else: h.flash_error('ERROR: Mail could not be sent. Please try again later or contact the site admin.') redirect(id)
def check(*args, **kwargs): id = kwargs['id'] controller = args[0] pkg = tk.get_action('package_show')(None, {'id': id}) if not check_journal_role(pkg, 'admin') and not h.check_access('sysadmin'): tk.abort(403, 'Unauthorized') return func(controller, id)
def read_dataset(self, _id, _format=None): if not _format: _format = check_access_header() if not _format: if toolkit.check_ckan_version(max_version='2.8.99'): return read_endpoint(_id) else: return read_endpoint(_get_package_type(_id), _id) _profiles = toolkit.request.params.get('profiles') if _profiles: _profiles = _profiles.split(',') toolkit.response.headers.update( {'Content-type': CONTENT_TYPES[_format]}) try: result = toolkit.get_action('dcat_dataset_show')({}, {'id': _id, 'format': _format, 'profiles': _profiles}) except toolkit.ObjectNotFound: toolkit.abort(404) except (toolkit.ValidationError, RDFProfileException) as e: toolkit.abort(409, str(e)) return result
def login(self): '''Handle an attempt to login using Persona. ''' # Get the params that were posted to /user/login. params = toolkit.request.params if 'assertion' in params: # We've found an assetion from Persona, try to verify it. try: email = verify_login(params['assertion']) except PersonaVerificationError, e: toolkit.abort(500) user = get_user(email) if not user: # A user with this email address doesn't yet exist in CKAN, # so create one. user = toolkit.get_action('user_create')( context={'ignore_auth': True}, data_dict={'email': email, 'name': generate_user_name(email), 'password': generate_password()}) # Store the name of the verified logged-in user in the Beaker # sesssion store. pylons.session['ckanext-persona-user'] = user['name'] pylons.session['ckanext-persona-email'] = email pylons.session.save()
def request_reset(self): context = {"model": model, "session": model.Session, "user": toolkit.c.user, "auth_user_obj": toolkit.c.userobj} data_dict = {"id": toolkit.request.params.get("user")} try: toolkit.check_access("request_reset", context) except toolkit.NotAuthorized: toolkit.abort(401, toolkit._("Unauthorized to request reset password.")) if toolkit.request.method == "POST": id = toolkit.request.params.get("user") context = {"model": model, "user": toolkit.c.user} data_dict = {"id": id} user_obj = None try: toolkit.get_action("user_show")(context, data_dict) user_obj = context["user_obj"] except toolkit.ObjectNotFound: h.flash_error(toolkit._("No such user: %s") % id) if user_obj: try: mailer.send_reset_link(user_obj) h.flash_success(toolkit._("Please check your inbox for " "a reset code.")) h.redirect_to("/") except mailer.MailerException, e: h.flash_error(toolkit._("Could not send reset link: %s") % unicode(e))
def save_content(self, context=None): context = {'model': model, 'session': model.Session, 'auth_user_obj': c.userobj, 'for_view': True} try: _check_access('is_data_curator', context) except toolkit.NotAuthorized, e: toolkit.abort(401, e.extra_msg)
def my_privates(self, username): if not toolkit.c.userobj or toolkit.c.user != username or not toolkit.c.userobj.sysadmin: return toolkit.abort(403, ) user = model.User.get(username) if not user: return toolkit.abort(404, 'User {0} not found'.format(username)) queryset = self._my_datasets_query(user, True).limit(20) return self.json_response(self._build_datasets(queryset))
def __before__(self, action, **params): super(InventoryAdminController, self).__before__(action, **params) context = {'user': c.user, 'auth_user_obj': c.userobj} try: check_access('sysadmin', context, {}) except NotAuthorized: # TODO @palcu: you should only be in a special group, not be sysadmin abort(401, 'Need to be system administrator to check inventory')
def organization_dcat_validation(self, _id): try: dcat_validation_dict = \ toolkit.get_action('dcat_validation')({}, {'id': _id}) except toolkit.ObjectNotFound: toolkit.abort(404, toolkit._('Organization not found')) toolkit.response.headers.update({'Content-type': 'application/json'}) return json.dumps(dcat_validation_dict)
def result_page(offset, limit): try: return get_action('datastore_search')(None, { 'resource_id': resource_id, 'limit': PAGINATE_BY if limit is None else min(PAGINATE_BY, limit), 'offset': offset, }) except ObjectNotFound: abort(404, _('DataStore resource not found'))
def start_writer(fields): if fmt == 'csv': return csv_writer(response, fields, resource_id, bom) if fmt == 'tsv': return tsv_writer(response, fields, resource_id, bom) if fmt == 'json': return json_writer(response, fields, resource_id, bom) if fmt == 'xml': return xml_writer(response, fields, resource_id, bom) abort(400, _( u'format: must be one of %s') % u', '.join(DUMP_FORMATS))
def dump(self, resource_id): try: offset = int_validator(request.GET.get('offset', 0), {}) except Invalid as e: abort(400, u'offset: ' + e.error) try: limit = int_validator(request.GET.get('limit'), {}) except Invalid as e: abort(400, u'limit: ' + e.error) bom = boolean_validator(request.GET.get('bom'), {}) fmt = request.GET.get('format', 'csv') def start_writer(fields): if fmt == 'csv': return csv_writer(response, fields, resource_id, bom) if fmt == 'tsv': return tsv_writer(response, fields, resource_id, bom) if fmt == 'json': return json_writer(response, fields, resource_id, bom) if fmt == 'xml': return xml_writer(response, fields, resource_id, bom) abort(400, _( u'format: must be one of %s') % u', '.join(DUMP_FORMATS)) def result_page(offset, limit): try: return get_action('datastore_search')(None, { 'resource_id': resource_id, 'limit': PAGINATE_BY if limit is None else min(PAGINATE_BY, limit), 'offset': offset, }) except ObjectNotFound: abort(404, _('DataStore resource not found')) result = result_page(offset, limit) columns = [x['id'] for x in result['fields']] with start_writer(result['fields']) as wr: while True: if limit is not None and limit <= 0: break for record in result['records']: wr.writerow([record[column] for column in columns]) if len(result['records']) < PAGINATE_BY: break offset += PAGINATE_BY if limit is not None: limit -= PAGINATE_BY result = result_page(offset, limit)
def broken_links_by_email(self): try: report = toolkit.get_action( "ckanext_deadoralive_broken_links_by_email")(data_dict={}) except toolkit.NotAuthorized: toolkit.abort(401) extra_vars = {"report": report} return toolkit.render("broken_links_by_email.html", extra_vars=extra_vars)
def dcat_json(self): data_dict = { 'page': toolkit.request.params.get('page'), 'modified_since': toolkit.request.params.get('modified_since'), } try: datasets = toolkit.get_action('dcat_datasets_list')({}, data_dict) except toolkit.ValidationError, e: toolkit.abort(409, str(e))
def all_reported_issues(self, organization_id): '''show all issues over max_strikes and are not moderated''' try: issues, organization = all_reported_issues(organization_id) extra_vars = { 'issues': issues.get('results', []), 'organization': organization, } return toolkit.render("issues/moderation.html", extra_vars=extra_vars) except toolkit.ObjectNotFound: toolkit.abort(404, toolkit._('Organization not found'))
def get_status(self, request_id): context = { 'model': model, 'session': model.Session, } try: request_status = toolkit.get_action('get_change_request')(context, {'id': request_id}) if not request_status: toolkit.abort(404, toolkit._( 'Request {0} not found'.format(request_id))) except toolkit.ValidationError, e: helpers.flash_error('{0}'.format(e.error_dict['message']))
def _call_action(self, action, data_dict=None, key=None): context = dict(user=toolkit.c.user) if data_dict is None: data_dict = dict(toolkit.request.params) action_function = toolkit.get_action(action) try: result = action_function(context, data_dict) except toolkit.NotAuthorized: toolkit.abort(403) toolkit.response.headers['Content-Type'] = 'application/json' if key: result = result[key] return json.dumps(result)
def config(self): #在「/ckan-admin/dsp-integrate」頁面render之前,先確認使用者是否為sysadmin。 context = {'model': c.model, 'user': c.user, 'auth_user_obj': c.userobj} try: toolkit.check_access('sysadmin', context, {}) except toolkit.NotAuthorized: toolkit.abort(401, _('Need to be system administrator to administer') ) c.revision_change_state_allowed = True return toolkit.render('admin/sync.html')
def proxy_resource(context: Context, data_dict: DataDict): u'''Chunked proxy for resources. To make sure that the file is not too large, first, we try to get the content length from the headers. If the headers to not contain a content length (if it is a chinked response), we only transfer as long as the transferred data is less than the maximum file size. ''' resource_id = data_dict[u'resource_id'] log.info(u'Proxify resource {id}'.format(id=resource_id)) try: resource = get_action(u'resource_show')(context, {u'id': resource_id}) except logic.NotFound: return abort(404, _(u'Resource not found')) url = resource[u'url'] parts = urlsplit(url) if not parts.scheme or not parts.netloc: return abort(409, _(u'Invalid URL.')) max_file_size = config.get_value(u'ckan.resource_proxy.max_file_size') response = make_response() try: # first we try a HEAD request which may not be supported did_get = False r = requests.head(url, timeout=TIMEOUT) # Servers can refuse HEAD requests. 405 is the appropriate # response, but 400 with the invalid method mentioned in the # text, or a 403 (forbidden) status is also possible (#2412, # #2530) if r.status_code in (400, 403, 405): r = requests.get(url, timeout=TIMEOUT, stream=True) did_get = True r.raise_for_status() cl = r.headers.get(u'content-length') if cl and int(cl) > max_file_size: return abort( 409, (u'Content is too large to be proxied. Allowed' u'file size: {allowed}, Content-Length: {actual}.').format( allowed=max_file_size, actual=cl)) if not did_get: r = requests.get(url, timeout=TIMEOUT, stream=True) response.headers[u'content-type'] = r.headers[u'content-type'] response.charset = r.encoding length = 0 chunk_size = config.get_value(u'ckan.resource_proxy.chunk_size') for chunk in r.iter_content(chunk_size=chunk_size): response.stream.write(chunk) length += len(chunk) if length >= max_file_size: return abort(409, headers={u'content-encoding': u''}, detail=u'Content is too large to be proxied.') except requests.exceptions.HTTPError as error: details = u'Could not proxy resource. Server responded with %s %s' % ( error.response.status_code, error.response.reason) return abort(409, detail=details) except requests.exceptions.ConnectionError as error: details = u'''Could not proxy resource because a connection error occurred. %s''' % error return abort(502, detail=details) except requests.exceptions.Timeout: details = u'Could not proxy resource because the connection timed out.' return abort(504, detail=details) return response
tk.abort(400, tk._(u'Integrity Error')) except tk.ValidationError, e: errors = e.error_dict error_summary = e.error_summary return self.new(data_dict, errors, error_summary) def _save_edit(self, id, context): try: data_dict = clean_dict( dict_fns.unflatten( tuplize_dict(parse_params(tk.request.params)))) data_dict['id'] = id context['message'] = data_dict.get('log_message', '') context['allow_partial_update'] = True metadata_schema = tk.get_action('metadata_schema_update')( context, data_dict) tk.h.redirect_to( 'metadata_schema_read', id=metadata_schema['name'], metadata_standard_id=tk.c.metadata_standard['name']) except tk.ObjectNotFound: tk.abort(404, tk._('Metadata schema not found')) except tk.NotAuthorized, e: tk.abort(403, e.message) except dict_fns.DataError: tk.abort(400, tk._(u'Integrity Error')) except tk.ValidationError, e: errors = e.error_dict error_summary = e.error_summary return self.edit(id, data_dict, errors, error_summary)
class MetadataSchemaController(tk.BaseController): def _set_metadata_standard_context(self, metadata_standard_id): if metadata_standard_id and not tk.c.metadata_standard: context = { 'model': model, 'session': model.Session, 'user': tk.c.user } data_dict = {'id': metadata_standard_id} try: tk.c.metadata_standard = tk.get_action( 'metadata_standard_show')(context, data_dict) except tk.ObjectNotFound: tk.abort(404, tk._('Metadata standard not found')) except tk.NotAuthorized: tk.abort(403, tk._('Not authorized to see this page')) def index(self, metadata_standard_id=None): self._set_metadata_standard_context(metadata_standard_id) page = tk.h.get_page_number(tk.request.params) or 1 items_per_page = 21 context = { 'model': model, 'session': model.Session, 'user': tk.c.user, 'for_view': True } q = tk.c.q = tk.request.params.get('q', '') sort_by = tk.c.sort_by_selected = tk.request.params.get('sort') try: tk.check_access('site_read', context) tk.check_access('metadata_schema_list', context) except tk.NotAuthorized: tk.abort(403, tk._('Not authorized to see this page')) if tk.c.userobj: context['user_id'] = tk.c.userobj.id context['user_is_admin'] = tk.c.userobj.sysadmin try: data_dict_global_results = { 'metadata_standard_id': metadata_standard_id, 'all_fields': False, 'q': q, 'sort': sort_by, 'type': 'metadata_schema', } global_results = tk.get_action('metadata_schema_list')( context, data_dict_global_results) except tk.ValidationError as e: if e.error_dict and e.error_dict.get('message'): msg = e.error_dict['message'] else: msg = str(e) tk.h.flash_error(msg) tk.c.page = helpers.Page([], 0) return tk.render('metadata_schema/index.html') data_dict_page_results = { 'metadata_standard_id': metadata_standard_id, 'all_fields': True, 'q': q, 'sort': sort_by, 'limit': items_per_page, 'offset': items_per_page * (page - 1), } page_results = tk.get_action('metadata_schema_list')( context, data_dict_page_results) tk.c.page = helpers.Page( collection=global_results, page=page, url=tk.h.pager_url, items_per_page=items_per_page, ) tk.c.page.items = page_results return tk.render('metadata_schema/index.html') def new(self, data=None, errors=None, error_summary=None, metadata_standard_id=None): self._set_metadata_standard_context(metadata_standard_id) context = { 'model': model, 'session': model.Session, 'user': tk.c.user, 'save': 'save' in tk.request.params } try: tk.check_access('metadata_schema_create', context) except tk.NotAuthorized: tk.abort(403, tk._('Unauthorized to create a metadata schema')) if context['save'] and not data and tk.request.method == 'POST': return self._save_new(context) data = data or {} errors = errors or {} error_summary = error_summary or {} vars = { 'data': data, 'errors': errors, 'error_summary': error_summary, 'action': 'new', 'organization_lookup_list': self._organization_lookup_list(), 'infrastructure_lookup_list': self._infrastructure_lookup_list() } tk.c.is_sysadmin = authz.is_sysadmin(tk.c.user) tk.c.form = tk.render('metadata_schema/edit_form.html', extra_vars=vars) return tk.render('metadata_schema/new.html') def edit(self, id, data=None, errors=None, error_summary=None, metadata_standard_id=None): self._set_metadata_standard_context(metadata_standard_id) context = { 'model': model, 'session': model.Session, 'user': tk.c.user, 'save': 'save' in tk.request.params, 'for_edit': True } data_dict = {'id': id} if context['save'] and not data and tk.request.method == 'POST': return self._save_edit(id, context) try: old_data = tk.get_action('metadata_schema_show')(context, data_dict) data = data or old_data except (tk.ObjectNotFound, tk.NotAuthorized): tk.abort(404, tk._('Metadata schema not found')) tk.c.metadata_schema = old_data try: tk.check_access('metadata_schema_update', context) except tk.NotAuthorized: tk.abort( 403, tk._('User %r not authorized to edit %s') % (tk.c.user, id)) errors = errors or {} vars = { 'data': data, 'errors': errors, 'error_summary': error_summary, 'action': 'edit', 'organization_lookup_list': self._organization_lookup_list(), 'infrastructure_lookup_list': self._infrastructure_lookup_list() } tk.c.form = tk.render('metadata_schema/edit_form.html', extra_vars=vars) return tk.render('metadata_schema/edit.html') def delete(self, id, metadata_standard_id=None): if 'cancel' in tk.request.params: tk.h.redirect_to('metadata_schema_edit', id=id, metadata_standard_id=metadata_standard_id) context = {'model': model, 'session': model.Session, 'user': tk.c.user} try: tk.check_access('metadata_schema_delete', context, {'id': id}) except tk.NotAuthorized: tk.abort(403, tk._('Unauthorized to delete metadata schema')) try: if tk.request.method == 'POST': tk.get_action('metadata_schema_delete')(context, {'id': id}) tk.h.flash_notice(tk._('Metadata Schema has been deleted.')) tk.h.redirect_to('metadata_schema_index', metadata_standard_id=metadata_standard_id) tk.c.metadata_schema = tk.get_action('metadata_schema_show')( context, { 'id': id }) except tk.NotAuthorized: tk.abort(403, tk._('Unauthorized to delete metadata schema')) except tk.ObjectNotFound: tk.abort(404, tk._('Metadata_schema not found')) return tk.render('metadata_schema/confirm_delete.html') def read(self, id, metadata_standard_id=None): self._set_metadata_standard_context(metadata_standard_id) context = { 'model': model, 'session': model.Session, 'user': tk.c.user, 'for_view': True } tk.c.metadata_schema = tk.get_action('metadata_schema_show')(context, { 'id': id }) return tk.render('metadata_schema/read.html') def about(self, id, metadata_standard_id=None): self._set_metadata_standard_context(metadata_standard_id) context = { 'model': model, 'session': model.Session, 'user': tk.c.user, 'for_view': True } tk.c.metadata_schema = tk.get_action('metadata_schema_show')(context, { 'id': id }) return tk.render('metadata_schema/about.html') def activity(self, id, metadata_standard_id=None): self._set_metadata_standard_context(metadata_standard_id) context = { 'model': model, 'session': model.Session, 'user': tk.c.user, 'for_view': True } tk.c.metadata_schema = tk.get_action('metadata_schema_show')(context, { 'id': id }) return tk.render('metadata_schema/activity_stream.html') @staticmethod def _organization_lookup_list(): """ Return a list of {'value': name, 'text': display_name} dicts for populating the organization select control. """ context = {'model': model, 'session': model.Session, 'user': tk.c.user} organizations = tk.get_action('organization_list')(context, { 'all_fields': True }) return [{'value': '', 'text': tk._('(All)')}] + \ [{'value': organization['name'], 'text': organization['display_name']} for organization in organizations] @staticmethod def _infrastructure_lookup_list(): """ Return a list of {'value': name, 'text': display_name} dicts for populating the infrastructure select control. """ context = {'model': model, 'session': model.Session, 'user': tk.c.user} infrastructures = tk.get_action('infrastructure_list')( context, { 'all_fields': True }) return [{'value': '', 'text': tk._('(All)')}] + \ [{'value': infrastructure['name'], 'text': infrastructure['display_name']} for infrastructure in infrastructures] def _save_new(self, context): try: data_dict = clean_dict( dict_fns.unflatten( tuplize_dict(parse_params(tk.request.params)))) context['message'] = data_dict.get('log_message', '') metadata_schema = tk.get_action('metadata_schema_create')( context, data_dict) tk.h.redirect_to( 'metadata_schema_read', id=metadata_schema['name'], metadata_standard_id=tk.c.metadata_standard['name']) except tk.ObjectNotFound: tk.abort(404, tk._('Metadata schema not found')) except tk.NotAuthorized, e: tk.abort(403, e.message) except dict_fns.DataError: tk.abort(400, tk._(u'Integrity Error'))
def index(self, metadata_standard_id=None): self._set_metadata_standard_context(metadata_standard_id) page = tk.h.get_page_number(tk.request.params) or 1 items_per_page = 21 context = { 'model': model, 'session': model.Session, 'user': tk.c.user, 'for_view': True } q = tk.c.q = tk.request.params.get('q', '') sort_by = tk.c.sort_by_selected = tk.request.params.get('sort') try: tk.check_access('site_read', context) tk.check_access('metadata_schema_list', context) except tk.NotAuthorized: tk.abort(403, tk._('Not authorized to see this page')) if tk.c.userobj: context['user_id'] = tk.c.userobj.id context['user_is_admin'] = tk.c.userobj.sysadmin try: data_dict_global_results = { 'metadata_standard_id': metadata_standard_id, 'all_fields': False, 'q': q, 'sort': sort_by, 'type': 'metadata_schema', } global_results = tk.get_action('metadata_schema_list')( context, data_dict_global_results) except tk.ValidationError as e: if e.error_dict and e.error_dict.get('message'): msg = e.error_dict['message'] else: msg = str(e) tk.h.flash_error(msg) tk.c.page = helpers.Page([], 0) return tk.render('metadata_schema/index.html') data_dict_page_results = { 'metadata_standard_id': metadata_standard_id, 'all_fields': True, 'q': q, 'sort': sort_by, 'limit': items_per_page, 'offset': items_per_page * (page - 1), } page_results = tk.get_action('metadata_schema_list')( context, data_dict_page_results) tk.c.page = helpers.Page( collection=global_results, page=page, url=tk.h.pager_url, items_per_page=items_per_page, ) tk.c.page.items = page_results return tk.render('metadata_schema/index.html')
def submit_feedback(self): """ Retrieves the necessary data and sends a feedback email to the appropriate recipient. """ context = { 'model': model, 'session': model.Session, 'user': g.user, 'for_view': True, 'auth_user_obj': g.userobj } protocol, host = h.get_site_protocol_and_host() full_current_url = h.full_current_url() if protocol is not None and host is not None and host in full_current_url: package = get_action('package_show')(context, { 'id': request.GET['id'] }) if 'error' not in package: data_dict = {} not_provided = 'Not provided' if 'name' not in request.GET: data_dict['name'] = not_provided else: data_dict['name'] = request.GET['name'].encode('utf8') if 'email' not in request.GET: data_dict['email'] = not_provided else: data_dict['email'] = request.GET['email'].encode('utf8') if 'comments' not in request.GET: data_dict['comments'] = not_provided else: data_dict['comments'] = request.GET['comments'].encode( 'utf8') data_dict['resource_id'] = request.GET.get('resource_id', '') data_dict['captcha'] = request.GET.get('captcha', '') if (data_dict.get('captcha', '') or request.GET.get( 'captchaCatch', 'none') not in ['dev', 'prod']): # Do not indicate failure or success since captcha was filled likely bot; # 7 is the expected arguments in the query string; # captchaCatch is serverside generated value hence can either be 'dev' or 'prod' redirect_to('/') return package # If there is value for either maintenance_email or author_email, use that. # If both of them null then send the email to [email protected] # Logic written to maintain legacy data # Once all the records in database have 'maintainer_email', # remove this and feedback_email = package.get('maintainer_email', '') feedback_email = package.get('maintainer_email', '') if not feedback_email: feedback_email = package.get('author_email', '') if not feedback_email: feedback_email = '*****@*****.**' if 'organization' in package and package['organization']: feedback_organisation = _strip_non_ascii( package['organization'].get('title', '')) else: feedback_organisation = 'None' feedback_resource_name = '' feedback_dataset = _strip_non_ascii(package.get('title', '')) package_name = _strip_non_ascii(package.get('name', '')) feedback_origins = "{0}/dataset/{1}".format(host, package_name) if data_dict['resource_id'] != '': feedback_origins = "{0}/resource/{1}".format( feedback_origins, data_dict['resource_id']) package_resources = package.get('resources', []) for resource in package_resources: if data_dict['resource_id'] == resource.get('id'): feedback_resource_name = _strip_non_ascii( resource.get('name', '')) email_subject = '{0} Feedback {1} {2}'.format( host, feedback_dataset, feedback_resource_name) email_recipient_name = 'All' email_to = (config.get('feedback_form_recipients', '')).split(',') if feedback_email != '' and feedback_email: email_to.append(feedback_email) else: feedback_email = '' email_to = [e for e in email_to if e is not None] email_to = [i.strip() for i in email_to if i.strip() != ''] if email_to: email_body = "Name: {0} \r\nEmail: {1} \r\nComments: {2} \r\nFeedback Organisation: {3} \r\n" \ "Feedback Email: {4} \r\nFeedback Dataset: {5} \r\nFeedback Resource: {6} \r\n" \ "Feedback URL: {7}://{8}".format( cgi.escape(_strip_non_ascii(data_dict['name'])), cgi.escape(_strip_non_ascii(data_dict['email'])), cgi.escape(_strip_non_ascii(data_dict['comments'])), cgi.escape(feedback_organisation), cgi.escape(_strip_non_ascii(feedback_email)), cgi.escape(feedback_dataset), cgi.escape(feedback_resource_name), cgi.escape(protocol), cgi.escape(feedback_origins) ) try: _feedback_mail_recipient(email_recipient_name, email_to, g.site_title, g.site_url, email_subject, email_body) except Exception: return abort( 404, 'This form submission is invalid or CKAN mail is not configured.' ) # Redirect to home page if no thanks page is found success_redirect = config.get('feedback_redirection', '/') req = requests.get(protocol + '://' + host + success_redirect, verify=False) if req.status_code == requests.codes.ok: redirect_to(success_redirect) else: redirect_to('/') else: abort(404, 'Form submission is invalid no recipients.') return package else: abort(404, 'Invalid request source')
def package_history(id: str, activity_id: str) -> Union[Response, str]: context = cast( Context, { "model": model, "session": model.Session, "user": tk.g.user, "for_view": True, "auth_user_obj": tk.g.userobj, }, ) data_dict = {"id": id, "include_tracking": True} # check if package exists try: pkg_dict = tk.get_action("package_show")(context, data_dict) pkg = context["package"] except (tk.ObjectNotFound, tk.NotAuthorized): return tk.abort(404, tk._("Dataset not found")) # if the user specified a package id, redirect to the package name if ( data_dict["id"] == pkg_dict["id"] and data_dict["id"] != pkg_dict["name"] ): return tk.h.redirect_to( "activity.package_history", id=pkg_dict["name"], activity_id=activity_id, ) tk.g.pkg_dict = pkg_dict tk.g.pkg = pkg # NB templates should not use g.pkg, because it takes no account of # activity_id # view an 'old' version of the package, as recorded in the # activity stream try: activity = tk.get_action("activity_show")( context, {"id": activity_id, "include_data": True} ) except tk.ObjectNotFound: tk.abort(404, tk._("Activity not found")) except tk.NotAuthorized: tk.abort(403, tk._("Unauthorized to view activity data")) current_pkg = pkg_dict try: pkg_dict = activity["data"]["package"] except KeyError: tk.abort(404, tk._("Dataset not found")) if "id" not in pkg_dict or "resources" not in pkg_dict: log.info( "Attempt to view unmigrated or badly migrated dataset " "{} {}".format(id, activity_id) ) tk.abort( 404, tk._("The detail of this dataset activity is not available") ) if pkg_dict["id"] != current_pkg["id"]: log.info( "Mismatch between pkg id in activity and URL {} {}".format( pkg_dict["id"], current_pkg["id"] ) ) # the activity is not for the package in the URL - don't allow # misleading URLs as could be malicious tk.abort(404, tk._("Activity not found")) # The name is used lots in the template for links, so fix it to be # the current one. It's not displayed to the user anyway. pkg_dict["name"] = current_pkg["name"] # Earlier versions of CKAN only stored the package table in the # activity, so add a placeholder for resources, or the template # will crash. pkg_dict.setdefault("resources", []) # can the resources be previewed? for resource in pkg_dict["resources"]: resource_views = tk.get_action("resource_view_list")( context, {"id": resource["id"]} ) resource["has_views"] = len(resource_views) > 0 package_type = pkg_dict["type"] or "dataset" _setup_template_variables(context, {"id": id}, package_type=package_type) return tk.render( "package/history.html", { "dataset_type": package_type, "pkg_dict": pkg_dict, "pkg": pkg, }, )
def package_activity(id: str) -> Union[Response, str]: # noqa """Render this package's public activity stream page.""" after = tk.h.get_request_param("after") before = tk.h.get_request_param("before") activity_type = tk.h.get_request_param("activity_type") context = cast( Context, { "model": model, "session": model.Session, "user": tk.g.user, "for_view": True, "auth_user_obj": tk.g.userobj, }, ) data_dict = {"id": id} base_limit = tk.config.get_value("ckan.activity_list_limit") max_limit = tk.config.get_value("ckan.activity_list_limit_max") limit = min(base_limit, max_limit) activity_types = [activity_type] if activity_type else None is_first_page = after is None and before is None try: pkg_dict = tk.get_action("package_show")(context, data_dict) activity_dict = { "id": pkg_dict["id"], "after": after, "before": before, # ask for one more just to know if this query has more results "limit": limit + 1, "activity_types": activity_types, } pkg = context["package"] package_activity_stream = tk.get_action("package_activity_list")( context, activity_dict ) dataset_type = pkg_dict["type"] or "dataset" except tk.ObjectNotFound: return tk.abort(404, tk._("Dataset not found")) except tk.NotAuthorized: return tk.abort(403, tk._("Unauthorized to read dataset %s") % id) except tk.ValidationError: return tk.abort(400, tk._("Invalid parameters")) prev_page = None next_page = None has_more = len(package_activity_stream) > limit # remove the extra item if exists if has_more: if after: # drop the first element package_activity_stream.pop(0) else: # drop the last element package_activity_stream.pop() # if "after", we came from the next page. So it exists # if "before" (or is_first_page), we only show next page if we know # we have more rows if after or (has_more and (before or is_first_page)): before_time = datetime.fromisoformat( package_activity_stream[-1]["timestamp"] ) next_page = tk.h.url_for( "dataset.activity", id=id, activity_type=activity_type, before=before_time.timestamp(), ) # if "before", we came from the previous page. So it exists # if "after", we only show previous page if we know # we have more rows if before or (has_more and after): after_time = datetime.fromisoformat( package_activity_stream[0]["timestamp"] ) prev_page = tk.h.url_for( "dataset.activity", id=id, activity_type=activity_type, after=after_time.timestamp(), ) return tk.render( "package/activity.html", { "dataset_type": dataset_type, "pkg_dict": pkg_dict, "pkg": pkg, "activity_stream": package_activity_stream, "id": id, # i.e. package's current name "limit": limit, "has_more": has_more, "activity_type": activity_type, "activity_types": VALIDATORS_PACKAGE_ACTIVITY_TYPES.keys(), "prev_page": prev_page, "next_page": next_page, }, )
def resource_history(id: str, resource_id: str, activity_id: str) -> str: context = cast( Context, { "model": model, "session": model.Session, "user": tk.g.user, "auth_user_obj": tk.g.userobj, "for_view": True, }, ) try: package = tk.get_action("package_show")(context, {"id": id}) except (tk.ObjectNotFound, tk.NotAuthorized): return tk.abort(404, tk._("Dataset not found")) # view an 'old' version of the package, as recorded in the # activity stream current_pkg = package try: activity = context["session"].query(Activity).get(activity_id) assert activity package = activity.data["package"] except AttributeError: tk.abort(404, tk._("Dataset not found")) if package["id"] != current_pkg["id"]: log.info( "Mismatch between pkg id in activity and URL {} {}".format( package["id"], current_pkg["id"] ) ) # the activity is not for the package in the URL - don't allow # misleading URLs as could be malicious tk.abort(404, tk._("Activity not found")) # The name is used lots in the template for links, so fix it to be # the current one. It's not displayed to the user anyway. package["name"] = current_pkg["name"] # Don't crash on old (unmigrated) activity records, which do not # include resources or extras. package.setdefault("resources", []) resource = None for res in package.get("resources", []): if res["id"] == resource_id: resource = res break if not resource: return tk.abort(404, tk._("Resource not found")) # get package license info license_id = package.get("license_id") try: package["isopen"] = model.Package.get_license_register()[ license_id ].isopen() except KeyError: package["isopen"] = False resource_views = tk.get_action("resource_view_list")( context, {"id": resource_id} ) resource["has_views"] = len(resource_views) > 0 current_resource_view = None view_id = tk.request.args.get("view_id") if resource["has_views"]: if view_id: current_resource_view = [ rv for rv in resource_views if rv["id"] == view_id ] if len(current_resource_view) == 1: current_resource_view = current_resource_view[0] else: return tk.abort(404, tk._("Resource view not found")) else: current_resource_view = resource_views[0] # required for nav menu pkg = context["package"] dataset_type = pkg.type # TODO: remove tk.g.package = package tk.g.resource = resource tk.g.pkg = pkg tk.g.pkg_dict = package extra_vars: dict[str, Any] = { "resource_views": resource_views, "current_resource_view": current_resource_view, "dataset_type": dataset_type, "pkg_dict": package, "package": package, "resource": resource, "pkg": pkg, # NB it is the current version of the dataset, so ignores # activity_id. Still used though in resource views for # backward compatibility } return tk.render("package/resource_history.html", extra_vars)
def group_changes_multiple(is_organization: bool, group_type: str) -> str: """ Called when a user specifies a range of versions they want to look at changes between. Verifies that the range is valid and finds the set of activity diffs for the changes in the given version range, then re-renders changes.html with the list. """ set_org(is_organization) extra_vars = {} new_id = tk.h.get_request_param("new_id") old_id = tk.h.get_request_param("old_id") context = cast( Context, { "model": model, "session": model.Session, "user": tk.g.user, "auth_user_obj": tk.g.userobj, }, ) # check to ensure that the old activity is actually older than # the new activity old_activity = tk.get_action("activity_show")( context, {"id": old_id, "include_data": False} ) new_activity = tk.get_action("activity_show")( context, {"id": new_id, "include_data": False} ) old_timestamp = old_activity["timestamp"] new_timestamp = new_activity["timestamp"] t1 = datetime.strptime(old_timestamp, "%Y-%m-%dT%H:%M:%S.%f") t2 = datetime.strptime(new_timestamp, "%Y-%m-%dT%H:%M:%S.%f") time_diff = t2 - t1 # if the time difference is negative, just return the change that put us # at the more recent ID we were just looking at # TODO: do something better here - go back to the previous page, # display a warning that the user can't look at a sequence where # the newest item is older than the oldest one, etc if time_diff.total_seconds() < 0: return group_changes( tk.h.get_request_param("current_new_id"), group_type, is_organization, ) done = False current_id = new_id diff_list = [] while not done: try: activity_diff = tk.get_action("activity_diff")( context, { "id": current_id, "object_type": "group", "diff_type": "html", }, ) except tk.ObjectNotFound as e: log.info("Activity not found: {} - {}".format(str(e), current_id)) return tk.abort(404, tk._("Activity not found")) except tk.NotAuthorized: return tk.abort(403, tk._("Unauthorized to view activity data")) diff_list.append(activity_diff) if activity_diff["activities"][0]["id"] == old_id: done = True else: current_id = activity_diff["activities"][0]["id"] group_id: str = diff_list[0]["activities"][1]["data"]["group"]["id"] current_group_dict = tk.get_action(group_type + "_show")( context, {"id": group_id} ) group_activity_list = tk.get_action(group_type + "_activity_list")( context, {"id": group_id, "limit": 100} ) extra_vars: dict[str, Any] = { "activity_diffs": diff_list, "group_dict": current_group_dict, "group_activity_list": group_activity_list, "group_type": current_group_dict["type"], } return tk.render(_replace_group_org("group/changes.html"), extra_vars)
def _get_dashboard_context( filter_type: Optional[str] = None, filter_id: Optional[str] = None, q: Optional[str] = None, ) -> dict[str, Any]: """Return a dict needed by the dashboard view to determine context.""" def display_name(followee: dict[str, Any]) -> Optional[str]: """Return a display name for a user, group or dataset dict.""" display_name = followee.get("display_name") fullname = followee.get("fullname") title = followee.get("title") name = followee.get("name") return display_name or fullname or title or name if filter_type and filter_id: context = cast( Context, { "model": model, "session": model.Session, "user": tk.g.user, "auth_user_obj": tk.g.userobj, "for_view": True, }, ) data_dict: dict[str, Any] = { "id": filter_id, "include_num_followers": True, } followee = None action_functions = { "dataset": "package_show", "user": "******", "group": "group_show", "organization": "organization_show", } action_name = action_functions.get(filter_type) if action_name is None: tk.abort(404, tk._("Follow item not found")) action_function = tk.get_action(action_name) try: followee = action_function(context, data_dict) except (tk.ObjectNotFound, tk.NotAuthorized): tk.abort(404, tk._("{0} not found").format(filter_type)) if followee is not None: return { "filter_type": filter_type, "q": q, "context": display_name(followee), "selected_id": followee.get("id"), "dict": followee, } return { "filter_type": filter_type, "q": q, "context": tk._("Everything"), "selected_id": False, "dict": None, }
def restricted_request_access_form(self, package_id, resource_id, data=None, errors=None, error_summary=None): '''Redirects to form ''' user_id = toolkit.c.user if not user_id: toolkit.abort( 401, _('Access request form is available to logged in users only.')) context = { 'model': model, 'session': model.Session, 'user': user_id, 'save': 'save' in request.params } data = data or {} errors = errors or {} error_summary = error_summary or {} if (context['save']) and not data and not errors: return self._send_request(context) if not data: data['package_id'] = package_id data['resource_id'] = resource_id try: user = toolkit.get_action('user_show')(context, { 'id': user_id }) data['user_id'] = user_id data['user_name'] = user.get('display_name', user_id) data['user_email'] = user.get('email', '') resource_name = "" pkg = toolkit.get_action('package_show')(context, { 'id': package_id }) data['package_name'] = pkg.get('name') resources = pkg.get('resources', []) for resource in resources: if resource['id'] == resource_id: resource_name = resource['name'] break else: toolkit.abort(404, 'Dataset resource not found') # get mail contact_details = self._get_contact_details(pkg) except toolkit.ObjectNotFound: toolkit.abort(404, _('Dataset not found')) except Exception as e: log.warn('Exception Request Form: ' + repr(e)) toolkit.abort( 404, _('Exception retrieving dataset for the form (' + str(e) + ')')) except: toolkit.abort( 404, _('Unknown exception retrieving dataset for the form')) data['resource_name'] = resource_name data['maintainer_email'] = contact_details.get('contact_email', '') data['maintainer_name'] = contact_details.get('contact_name', '') else: pkg = data.get('pkg_dict', {}) extra_vars = { 'pkg_dict': pkg, 'data': data, 'errors': errors, 'error_summary': error_summary } return render('restricted/restricted_request_access_form.html', extra_vars=extra_vars)
def format_mapping(self): try: tk.check_access('sysadmin', {'user': g.user, model: model}) except tk.NotAuthorized: return tk.abort(403) if request.method == 'POST': old = request.POST.get('from') new = request.POST.get('to') if old and new: ids = set() res_query = model.Session.query(model.Resource).filter_by( format=old, state='active' ) for res in res_query: ids.add(res.package_id) res_query.update({'format': new}) model.Session.commit() for id in ids: clear(id) rebuild(id, defer_commit=True) commit() tk.h.flash_success( 'Updated. Records changed: {}'.format(len(ids)) ) return tk.redirect_to('format_mapping') defined = set( map(lambda (_1, fmt, _3): fmt, h.resource_formats().values()) ) db_formats = model.Session.query( model.Resource.format, func.count(model.Resource.id), func.count(model.PackageExtra.value) ).outerjoin( model.PackageExtra, (model.Resource.package_id == model.PackageExtra.package_id) & ((model.PackageExtra.key == 'harvest_portal') | (model.PackageExtra.key.is_(None))) ).group_by(model.Resource.format).filter( model.Resource.format != '', model.Resource.state == 'active' ) db_formats = db_formats.all() format_types = { f: { True: 'Partially external', e == 0: 'Local', t - e == 0: 'External' }[True] for (f, t, e) in db_formats } used = set(format_types) undefined = used - defined extra_vars = { 'undefined': undefined, 'defined': defined, 'format_types': format_types } return tk.render('admin/format_mapping.html', extra_vars)
def before_request(): try: context = dict(model=model, user=g.user, auth_user_obj=g.userobj) logic.check_access(u'sysadmin', context) except NotAuthorized: abort(403, _(u'Need to be system administrator to administer'))
def _add_or_reply(comment_type, content_item_id, content_type, parent_id=None): """ Allows the user to add a comment to an existing dataset or datarequest :param comment_type: Either 'new' or 'reply' :param content_item_id: :param content_type: string 'dataset' or 'datarequest' :return: """ content_type = 'dataset' if 'content_type' not in vars() else content_type context = {'model': model, 'user': c.user} data_dict = {'id': content_item_id} # Auth check to make sure the user can see this content item helpers.check_content_access(content_type, context, data_dict) try: # Load the content item helpers.get_content_item(content_type, context, data_dict) except: abort(403) if request.method == 'POST': data_dict = clean_dict( unflatten( tuplize_dict( parse_params( request_helpers.RequestHelper( request).get_post_params())))) data_dict['parent_id'] = c.parent.id if 'parent' in dir(c) else None data_dict['url'] = '/%s/%s' % (content_type, content_item_id if content_type == 'datarequest' else c.pkg.name) success = False try: res = get_action('comment_create')(context, data_dict) success = True except ValidationError as ve: log.debug(ve) if ve.error_dict and ve.error_dict.get('message'): msg = ve.error_dict['message'] else: msg = str(ve) h.flash_error(msg) except Exception as e: log.debug(e) abort(403) if success: email_notifications.notify_admins_and_comment_notification_recipients( helpers.get_org_id(content_type), toolkit.c.userobj, 'notification-new-comment', content_type, helpers.get_content_item_id(content_type), res['thread_id'], res['parent_id'] if comment_type == 'reply' else None, res['id'], c.pkg_dict['title'] if content_type == 'dataset' else c.datarequest['title'], res['content'] # content is the comment that has been cleaned up in the action comment_create ) if notification_helpers.comment_notification_recipients_enabled(): if comment_type == 'reply': # Add the user who submitted the reply to comment notifications for this thread notification_helpers.add_commenter_to_comment_notifications( toolkit.c.userobj.id, res['thread_id'], res['parent_id']) else: # Add the user who submitted the comment notifications for this new thread notification_helpers.add_commenter_to_comment_notifications( toolkit.c.userobj.id, res['thread_id'], res['id']) return h.redirect_to( helpers.get_redirect_url( content_type, content_item_id if content_type == 'datarequest' else c.pkg.name, 'comment_' + str(res['id']) if success else ('comment_form' if comment_type == 'new' else 'reply_' + str(parent_id)))) return helpers.render_content_template(content_type)
def view(self, report_name, organization=None, refresh=False): try: report = t.get_action('report_show')({}, {'id': report_name}) except t.NotAuthorized: t.abort(401) except t.ObjectNotFound: t.abort(404) # ensure correct url is being used if 'organization' in t.request.environ['pylons.routes_dict'] and \ 'organization' not in report['option_defaults']: t.redirect_to(helpers.relative_url_for(organization=None)) elif 'organization' not in t.request.environ['pylons.routes_dict'] and \ 'organization' in report['option_defaults'] and \ report['option_defaults']['organization']: org = report['option_defaults']['organization'] t.redirect_to(helpers.relative_url_for(organization=org)) if 'organization' in t.request.params: # organization should only be in the url - let the param overwrite # the url. t.redirect_to(helpers.relative_url_for()) # options options = Report.add_defaults_to_options(t.request.params, report['option_defaults']) option_display_params = {} if 'format' in options: format = options.pop('format') else: format = None if 'organization' in report['option_defaults']: options['organization'] = organization options_html = {} c.options = options # for legacy genshi snippets for option in options: if option not in report['option_defaults']: # e.g. 'refresh' param log.warn( 'Not displaying report option HTML for param %s as option not recognized' ) continue option_display_params = { 'value': options[option], 'default': report['option_defaults'][option] } try: options_html[option] = \ t.render_snippet('report/option_%s.html' % option, data=option_display_params) except TemplateNotFound: log.warn( 'Not displaying report option HTML for param %s as no template found' ) continue # Alternative way to refresh the cache - not in the UI, but is # handy for testing try: refresh = t.asbool(t.request.params.get('refresh')) if 'refresh' in options: options.pop('refresh') except ValueError: refresh = False # Refresh the cache if requested if t.request.method == 'POST' and not format: refresh = True if refresh: try: t.get_action('report_refresh')({}, { 'id': report_name, 'options': options }) except t.NotAuthorized: t.abort(401) # Don't want the refresh=1 in the url once it is done t.redirect_to(helpers.relative_url_for(refresh=None)) # Check for any options not allowed by the report for key in options: if key not in report['option_defaults']: t.abort(400, 'Option not allowed by report: %s' % key) try: data, report_date = t.get_action('report_data_get')( {}, { 'id': report_name, 'options': options }) except t.ObjectNotFound: t.abort(404) except t.NotAuthorized: t.abort(401) if format and format != 'html': ensure_data_is_dicts(data) anonymise_user_names(data, organization=options.get('organization')) if format == 'csv': try: key = t.get_action('report_key_get')({}, { 'id': report_name, 'options': options }) except t.NotAuthorized: t.abort(401) filename = 'report_%s.csv' % key t.response.headers['Content-Type'] = 'application/csv' t.response.headers['Content-Disposition'] = str( 'attachment; filename=%s' % (filename)) return make_csv_from_dicts(data['table']) elif format == 'json': t.response.headers['Content-Type'] = 'application/json' data['generated_at'] = report_date return json.dumps(data) else: t.abort(400, 'Format not known - try html, json or csv') are_some_results = bool(data['table'] if 'table' in data else data) # A couple of context variables for legacy genshi reports c.data = data c.options = options return t.render('report/view.html', extra_vars={ 'report': report, 'report_name': report_name, 'data': data, 'report_date': report_date, 'options': options, 'options_html': options_html, 'report_template': report['template'], 'are_some_results': are_some_results })