def before_dataset_search(self, search_params: dict[str, Any]): lang_set = set(self.LANGS) try: current_lang: str = request.environ['CKAN_LANG'] except TypeError as err: if str(err) == ('No object (name: request) has been registered ' 'for this thread'): # This happens when this code gets called as part of a paster # command rather then as part of an HTTP request. current_lang = config.get_value('ckan.locale_default') else: raise except KeyError: current_lang = config.get_value('ckan.locale_default') # fallback to default locale if locale not in suported langs if not current_lang in lang_set: current_lang = config.get_value('ckan.locale_default') # fallback to english if default locale is not supported if not current_lang in lang_set: current_lang = 'en' # treat current lang differenly so remove from set lang_set.remove(current_lang) # weight current lang more highly query_fields = 'title_%s^8 text_%s^4' % (current_lang, current_lang) for lang in lang_set: query_fields += ' title_%s^2 text_%s' % (lang, lang) search_params['qf'] = query_fields return search_params
def test_from_field_format(self, mail_server): msgs = mail_server.get_smtp_messages() assert msgs == [] # send email test_email = { "recipient_name": "Bob", "recipient_email": "*****@*****.**", "subject": "Meeting", "body": "The meeting is cancelled.", "headers": { "header1": "value1" }, } mailer.mail_recipient(**test_email) # check it went to the mock smtp server msgs = mail_server.get_smtp_messages() msg = msgs[0] expected_from_header = "{0} <{1}>".format( config.get_value("ckan.site_title"), config.get_value("smtp.mail_from")) assert expected_from_header in msg[3]
def set_cors_headers_for_response(response: Response) -> Response: u''' Set up Access Control Allow headers if either origin_allow_all is True, or the request Origin is in the origin_whitelist. ''' if request.headers.get(u'Origin'): cors_origin_allowed = None allow_all = config.get_value(u'ckan.cors.origin_allow_all') whitelisted = request.headers.get(u'Origin') in config.get_value( u'ckan.cors.origin_whitelist') if allow_all: cors_origin_allowed = '*' elif whitelisted: # set var to the origin to allow it. cors_origin_allowed: Optional[str] = request.headers.get(u'Origin') if cors_origin_allowed is not None: response.headers['Access-Control-Allow-Origin'] = \ cors_origin_allowed response.headers['Access-Control-Allow-Methods'] = \ 'POST, PUT, GET, DELETE, OPTIONS' response.headers['Access-Control-Allow-Headers'] = \ 'X-CKAN-API-KEY, Authorization, Content-Type' return response
def webassets_init(): global env static_path = get_webassets_path() public = config.get_value(u'ckan.base_public_folder') public_folder = os.path.abspath( os.path.join(os.path.dirname(__file__), u'..', public)) base_path = os.path.join(public_folder, u'base') env = Environment() env.directory = static_path env.debug = config.get_value(u'debug') env.url = u'/webassets/' add_public_path(base_path, u'/base/') logger.debug(u'Base path {0}'.format(base_path)) create_library(u'vendor', os.path.join(base_path, u'vendor')) create_library(u'base', os.path.join(base_path, u'javascript')) create_library(u'datapreview', os.path.join(base_path, u'datapreview')) create_library(u'css', os.path.join(base_path, u'css'))
def output_feed(results: list[dict[str, Any]], feed_title: str, feed_description: str, feed_link: str, feed_url: str, navigation_urls: dict[str, str], feed_guid: str) -> Response: author_name = config.get_value(u'ckan.feeds.author_name').strip() or \ config.get_value(u'ckan.site_id').strip() def remove_control_characters(s: str): if not s: return "" return "".join(ch for ch in s if unicodedata.category(ch)[0] != "C") # TODO: language feed_class: PFeedFactory = CKANFeed for plugin in plugins.PluginImplementations(plugins.IFeed): if hasattr(plugin, u'get_feed_class'): feed_class = plugin.get_feed_class() feed = feed_class( feed_title, feed_link, feed_description, language=u'en', author_name=author_name, feed_guid=feed_guid, feed_url=feed_url, previous_page=navigation_urls[u'previous'], next_page=navigation_urls[u'next'], first_page=navigation_urls[u'first'], last_page=navigation_urls[u'last'], ) for pkg in results: additional_fields: dict[str, Any] = {} for plugin in plugins.PluginImplementations(plugins.IFeed): if hasattr(plugin, u'get_item_additional_fields'): additional_fields = plugin.get_item_additional_fields(pkg) feed.add_item( title=pkg.get(u'title', u''), link=h.url_for(u'api.action', logic_function=u'package_show', id=pkg['id'], ver=3, _external=True), description=remove_control_characters(pkg.get(u'notes', u'')), updated=h.date_str_to_datetime(pkg.get(u'metadata_modified', '')), published=h.date_str_to_datetime(pkg.get(u'metadata_created', '')), unique_id=_create_atom_id(u'/dataset/%s' % pkg['id']), author_name=pkg.get(u'author', u''), author_email=pkg.get(u'author_email', u''), categories=[t[u'name'] for t in pkg.get(u'tags', [])], enclosure=_enclosure(pkg), **additional_fields) resp = make_response(feed.writeString(u'utf-8'), 200) resp.headers['Content-Type'] = u'application/atom+xml' return resp
def get_reset_link_body(user: model.User) -> str: extra_vars = { 'reset_link': get_reset_link(user), 'site_title': config.get_value('ckan.site_title'), 'site_url': config.get_value('ckan.site_url'), 'user_name': user.name, } # NOTE: This template is translated return render('emails/reset_password.txt', extra_vars)
def delete_package(self, pkg_dict: dict[str, Any]) -> None: conn = make_connection() query = "+%s:%s AND +(id:\"%s\" OR name:\"%s\") AND +site_id:\"%s\"" % \ (TYPE_FIELD, PACKAGE_TYPE, pkg_dict.get('id'), pkg_dict.get('id'), config.get_value('ckan.site_id')) try: commit = config.get_value('ckan.search.solr_commit') conn.delete(q=query, commit=commit) except Exception as e: log.exception(e) raise SearchIndexError(e)
def mail_recipient(recipient_name: str, recipient_email: str, subject: str, body: str, body_html: Optional[str] = None, headers: Optional[dict[str, Any]] = None, attachments: Optional[Iterable[Attachment]] = None) -> None: '''Sends an email to a an email address. .. note:: You need to set up the :ref:`email-settings` to able to send emails. :param recipient_name: the name of the recipient :type recipient: string :param recipient_email: the email address of the recipient :type recipient: string :param subject: the email subject :type subject: string :param body: the email body, in plain text :type body: string :param body_html: the email body, in html format (optional) :type body_html: string :headers: extra headers to add to email, in the form {'Header name': 'Header value'} :type: dict :attachments: a list of tuples containing file attachments to add to the email. Tuples should contain the file name and a file-like object pointing to the file contents:: [ ('some_report.csv', file_object), ] Optionally, you can add a third element to the tuple containing the media type. If not provided, it will be guessed using the ``mimetypes`` module:: [ ('some_report.csv', file_object, 'text/csv'), ] :type: list ''' site_title = config.get_value('ckan.site_title') site_url = config.get_value('ckan.site_url') return _mail_recipient(recipient_name, recipient_email, site_title, site_url, subject, body, body_html=body_html, headers=headers, attachments=attachments)
def _get_locales(): # FIXME this wants cleaning up and merging with get_locales_from_config() assert not config.get('lang'), \ ('"lang" config option not supported - please use ckan.locale_default ' 'instead.') locales_offered = config.get_value('ckan.locales_offered') filtered_out = config.get_value('ckan.locales_filtered_out') locale_default = config.get_value('ckan.locale_default') locale_order = config.get_value('ckan.locale_order') locales = ['en'] i18n_path = get_ckan_i18n_dir() # For every file in the ckan i18n directory see if babel can understand # the locale. If yes, add it to the available locales for locale in os.listdir(i18n_path): try: Locale.parse(locale) locales.append(locale) except (ValueError, UnknownLocaleError): # Babel does not know how to make a locale out of this. # This is fine since we are passing all files in the # ckan.i18n_directory here which e.g. includes the __init__.py pass assert locale_default in locales, \ 'default language "%s" not available' % locale_default locale_list = [] for locale in locales: # no duplicates if locale in locale_list: continue # if offered locales then check locale is offered if locales_offered and locale not in locales_offered: continue # remove if filtered out if locale in filtered_out: continue # ignore the default as it will be added first if locale == locale_default: continue locale_list.append(locale) # order the list if specified ordered_list = [locale_default] for locale in locale_order: if locale in locale_list: ordered_list.append(locale) # added so remove from our list locale_list.remove(locale) # add any remaining locales not ordered ordered_list += locale_list return ordered_list
def set_active_backend(cls, config: CKANConfig): """Choose most suitable backend depending on configuration :param config: configuration object :rtype: ckan.common.CKANConfig """ schema = config.get_value(u'ckan.datastore.write_url').split(u':')[0] read_schema = config.get_value( u'ckan.datastore.read_url').split(u':')[0] assert read_schema == schema, u'Read and write engines are different' cls._active_backend = cls._backends[schema]()
def make_plugin(secret=None, secretfile=None, cookie_name='auth_tkt', secure=False, include_ip=False, timeout=None, reissue_time=None, userid_checker=None): from repoze.who.utils import resolveDotted # ckan specifics: # Get secret from beaker setting if necessary if secret is None or secret == u'somesecret': secret = config[u'beaker.session.secret'] # Session timeout and reissue time for auth cookie if timeout is None and config.get_value(u'who.timeout'): timeout = config[u'who.timeout'] if reissue_time is None and config.get_value(u'who.reissue_time'): reissue_time = config['who.reissue_time'] if timeout is not None and reissue_time is None: reissue_time = int(math.ceil(int(timeout) * 0.1)) # Set httponly based on config value. Default is True httponly = config.get_value(u'who.httponly') # Set secure based on config value. Default is False secure = config.get_value(u'who.secure') # Set samesite based on config value. Default is lax samesite = config.get_value(u'who.samesite').lower() if samesite == 'none' and not secure: raise ValueError('SameSite=None requires the Secure attribute,' 'please set who.secure=True') # back to repoze boilerplate if (secret is None and secretfile is None): raise ValueError(u"One of 'secret' or 'secretfile' must not be None.") if (secret is not None and secretfile is not None): raise ValueError(u"Specify only one of 'secret' or 'secretfile'.") if secretfile: secretfile = os.path.abspath(os.path.expanduser(secretfile)) if not os.path.exists(secretfile): raise ValueError(u"No such 'secretfile': %s" % secretfile) secret = open(secretfile).read().strip() if timeout: timeout = int(timeout) if reissue_time: reissue_time = int(reissue_time) if userid_checker is not None: userid_checker = resolveDotted(userid_checker) plugin = CkanAuthTktCookiePlugin(httponly, samesite, secret, cookie_name, secure, _bool(include_ip), timeout, reissue_time, userid_checker) return plugin
def get_locales_from_config(): ''' despite the name of this function it gets the locales defined by the config AND also the locals available subject to the config. ''' locales_offered = config.get_value('ckan.locales_offered') filtered_out = config.get_value('ckan.locales_filtered_out') locale_default = [config.get_value('ckan.locale_default')] locale_order = config.get_value('ckan.locale_order') known_locales = get_locales() all_locales = (set(known_locales) | set(locales_offered) | set(locale_order) | set(locale_default)) all_locales -= set(filtered_out) return all_locales
def custom(): """ Custom atom feed """ q = request.args.get(u'q', u'') fq = u'' search_params = {} for (param, value) in request.args.items(): if param not in [u'q', u'page', u'sort'] \ and len(value) and not param.startswith(u'_'): search_params[param] = value fq += u'%s:"%s"' % (param, value) page = h.get_page_number(request.args) limit = config.get_value('ckan.feeds.limit') data_dict = { u'q': q, u'fq': fq, u'start': (page - 1) * limit, u'rows': limit, u'sort': request.args.get(u'sort', None) } item_count, results = _package_search(data_dict) navigation_urls = _navigation_urls( request.args, item_count=item_count, limit=data_dict['rows'], controller=u'feeds', action=u'custom') feed_url = _feed_url(request.args, controller=u'feeds', action=u'custom') atom_url = h._url_with_params(u'/feeds/custom.atom', search_params.items()) alternate_url = _alternate_url(request.args) site_title = config.get_value(u'ckan.site_title') return output_feed( results, feed_title=u'%s - Custom query' % site_title, feed_description=u'Recently created or updated' ' datasets on %s. Custom query: \'%s\'' % (site_title, q), feed_link=alternate_url, feed_guid=_create_atom_id(atom_url), feed_url=feed_url, navigation_urls=navigation_urls)
def get_webassets_path(): webassets_path = config.get_value(u'ckan.webassets.path') if not webassets_path: storage_path = config.get_value( u'ckan.storage_path') or tempfile.gettempdir() if storage_path: webassets_path = os.path.join(storage_path, u'webassets') if not webassets_path: raise RuntimeError( u'Either `ckan.webassets.path` or `ckan.storage_path` ' u'must be specified') return webassets_path
def handle_i18n(environ: Optional[dict[str, Any]] = None) -> None: u''' Strips the locale code from the requested url (eg '/sk/about' -> '/about') and sets environ variables for the language selected: * CKAN_LANG is the language code eg en, fr * CKAN_LANG_IS_DEFAULT is set to True or False * CKAN_CURRENT_URL is set to the current application url ''' environ = environ or request.environ assert environ locale_list = get_locales_from_config() default_locale = config.get_value(u'ckan.locale_default') # We only update once for a request so we can keep # the language and original url which helps with 404 pages etc if u'CKAN_LANG' not in environ: path_parts = environ[u'PATH_INFO'].split(u'/') if len(path_parts) > 1 and path_parts[1] in locale_list: environ[u'CKAN_LANG'] = path_parts[1] environ[u'CKAN_LANG_IS_DEFAULT'] = False # rewrite url if len(path_parts) > 2: environ[u'PATH_INFO'] = u'/'.join([u''] + path_parts[2:]) else: environ[u'PATH_INFO'] = u'/' else: environ[u'CKAN_LANG'] = default_locale environ[u'CKAN_LANG_IS_DEFAULT'] = True set_ckan_current_url(environ)
def get_ckan_i18n_dir(): path = config.get_value(u'ckan.i18n_directory') or os.path.join( _CKAN_DIR, u'i18n') if os.path.isdir(os.path.join(path, u'i18n')): path = os.path.join(path, u'i18n') return path
def index(): page_number = h.get_page_number(request.args) q = request.args.get('q', '') order_by = request.args.get('order_by', 'name') default_limit: int = config.get_value('ckan.user_list_limit') limit = int(request.args.get('limit', default_limit)) context = cast( Context, { u'return_query': True, u'user': current_user.name, u'auth_user_obj': current_user }) data_dict = {u'q': q, u'order_by': order_by} try: logic.check_access(u'user_list', context, data_dict) except logic.NotAuthorized: base.abort(403, _(u'Not authorized to see this page')) users_list = logic.get_action(u'user_list')(context, data_dict) page = h.Page(collection=users_list, page=page_number, url=h.pager_url, item_count=users_list.count(), items_per_page=limit) extra_vars: dict[str, Any] = { u'page': page, u'q': q, u'order_by': order_by } return base.render(u'user/list.html', extra_vars)
def index(): page_number = h.get_page_number(request.params) q = request.params.get(u'q', u'') order_by = request.params.get(u'order_by', u'name') limit = int( request.params.get(u'limit', config.get_value(u'ckan.user_list_limit'))) context = { u'return_query': True, u'user': g.user, u'auth_user_obj': g.userobj } data_dict = {u'q': q, u'order_by': order_by} try: logic.check_access(u'user_list', context, data_dict) except logic.NotAuthorized: base.abort(403, _(u'Not authorized to see this page')) users_list = logic.get_action(u'user_list')(context, data_dict) page = h.Page(collection=users_list, page=page_number, url=h.pager_url, item_count=users_list.count(), items_per_page=limit) extra_vars = {u'page': page, u'q': q, u'order_by': order_by} return base.render(u'user/list.html', extra_vars)
def post(self, id): context, user_dict = self._prepare(id) context[u'reset_password'] = True user_state = user_dict[u'state'] try: new_password = self._get_form_password() user_dict[u'password'] = new_password username = request.form.get(u'name') if (username is not None and username != u''): user_dict[u'name'] = username user_dict[u'reset_key'] = g.reset_key user_dict[u'state'] = model.State.ACTIVE logic.get_action(u'user_update')(context, user_dict) mailer.create_reset_key(context[u'user_obj']) signals.perform_password_reset.send(username, user=context[u'user_obj']) h.flash_success(_(u'Your password has been reset.')) return h.redirect_to( config.get_value(u'ckan.user_reset_landing_page')) except logic.NotAuthorized: h.flash_error(_(u'Unauthorized to edit user %s') % id) except logic.NotFound: h.flash_error(_(u'User not found')) except dictization_functions.DataError: h.flash_error(_(u'Integrity Error')) except logic.ValidationError as e: h.flash_error(u'%r' % e.error_dict) except ValueError as e: h.flash_error(str(e)) user_dict[u'state'] = user_state return base.render(u'user/perform_reset.html', {u'user_dict': user_dict})
def __iter__(self) -> Iterator[TInterface]: ''' When we upgraded pyutilib on CKAN 2.9 the order in which plugins were returned by `PluginImplementations` changed so we use this wrapper to maintain the previous order (which is the same as the ckan.plugins config option) ''' iterator = super(PluginImplementations, self).__iter__() plugin_lookup = {pf.name: pf for pf in iterator} plugins = config.get_value("ckan.plugins") if plugins is None: plugins = [] elif isinstance(plugins, str): # this happens when core declarations loaded and validated plugins = plugins.split() plugins_in_config = plugins + find_system_plugins() ordered_plugins = [] for pc in plugins_in_config: if pc in plugin_lookup: ordered_plugins.append(plugin_lookup[pc]) plugin_lookup.pop(pc) if plugin_lookup: # Any oustanding plugin not in the ini file (ie system ones), # add to the end of the iterator ordered_plugins.extend(plugin_lookup.values()) return iter(ordered_plugins)
def render_snippet(*template_names: str, **kw: Any) -> str: ''' Helper function for rendering snippets. Rendered html has comment tags added to show the template used. NOTE: unlike other render functions this takes a list of keywords instead of a dict for the extra template variables. :param template_names: the template to render, optionally with fallback values, for when the template can't be found. For each, specify the relative path to the template inside the registered tpl_dir. :type template_names: str :param kw: extra template variables to supply to the template :type kw: named arguments of any type that are supported by the template ''' last_exc = None for template_name in template_names: try: output = render(template_name, extra_vars=kw) if config.get_value('debug'): output = ( '\n<!-- Snippet %s start -->\n%s\n<!-- Snippet %s end -->' '\n' % (template_name, output, template_name)) return h.literal(output) except TemplateNotFound as exc: if exc.name == template_name: # the specified template doesn't exist - try the next # fallback, but store the exception in case it was # last one last_exc = exc continue # a nested template doesn't exist - don't fallback raise exc else: raise last_exc or TemplatesNotFound(template_names)
def get_and_send_notifications_for_user(user): # Parse the email_notifications_since config setting, email notifications # from longer ago than this time will not be sent. email_notifications_since = config.get_value( 'ckan.email_notifications_since') email_notifications_since = string_to_timedelta(email_notifications_since) email_notifications_since = (datetime.datetime.utcnow() - email_notifications_since) # FIXME: We are accessing model from lib here but I'm not sure what # else to do unless we add a get_email_last_sent() logic function which # would only be needed by this lib. email_last_sent = model.Dashboard.get(user['id']).email_last_sent activity_stream_last_viewed = (model.Dashboard.get( user['id']).activity_stream_last_viewed) since = max(email_notifications_since, email_last_sent, activity_stream_last_viewed) notifications = get_notifications(user, since) # TODO: Handle failures from send_email_notification. for notification in notifications: send_notification(user, notification) # FIXME: We are accessing model from lib here but I'm not sure what # else to do unless we add a update_email_last_sent() # logic function which would only be needed by this lib. dash = model.Dashboard.get(user['id']) dash.email_last_sent = datetime.datetime.utcnow() model.repo.commit()
def _register_error_handler(app: CKANApp): u'''Register error handler''' def error_handler(e: Exception) -> tuple[str, Optional[int]]: debug = config.get_value('debug') if isinstance(e, HTTPException): if debug: log.debug(e, exc_info=sys.exc_info) # type: ignore else: log.info(e) extra_vars = { u'code': e.code, u'content': e.description, u'name': e.name } return base.render(u'error_document_template.html', extra_vars), e.code log.error(e, exc_info=sys.exc_info) # type: ignore extra_vars = {u'code': [500], u'content': u'Internal server error'} return base.render(u'error_document_template.html', extra_vars), 500 for code in default_exceptions: app.register_error_handler(code, error_handler) if not app.debug and not app.testing: app.register_error_handler(Exception, error_handler) if config.get_value('email_to'): _setup_error_mail_handler(app)
def test_can_view(self): url_same_domain = urljoin(config.get_value('ckan.site_url'), '/resource.txt') url_different_domain = 'http://some.com/resource.txt' data_dict = { 'resource': { 'format': 'jsonp', 'url': url_different_domain } } assert self.p.can_view(data_dict) data_dict = {'resource': {'format': 'json', 'url': url_same_domain}} assert self.p.can_view(data_dict) data_dict = {'resource': {'format': 'xml', 'url': url_same_domain}} assert self.p.can_view(data_dict) data_dict = {'resource': {'format': 'txt', 'url': url_same_domain}} assert self.p.can_view(data_dict) data_dict = {'resource': {'format': 'foo', 'url': url_same_domain}} assert not self.p.can_view(data_dict) data_dict = { 'resource': { 'format': 'json', 'url': url_different_domain } } assert not self.p.can_view(data_dict)
def user_show(context: Context, data_dict: DataDict) -> AuthResult: # By default, user details can be read by anyone, but some properties like # the API key are stripped at the action level if not not logged in. if not config.get_value('ckan.auth.public_user_details'): return restrict_anon(context) else: return {'success': True}
def check_recaptcha(request): '''Check a user\'s recaptcha submission is valid, and raise CaptchaError on failure.''' recaptcha_private_key = config.get_value('ckan.recaptcha.privatekey') if not recaptcha_private_key: # Recaptcha not enabled return client_ip_address = request.environ.get('REMOTE_ADDR', 'Unknown IP Address') # reCAPTCHA v2 recaptcha_response_field = request.form.get('g-recaptcha-response', '') recaptcha_server_name = 'https://www.google.com/recaptcha/api/siteverify' # recaptcha_response_field will be unicode if there are foreign chars in # the user input. So we need to encode it as utf8 before urlencoding or # we get an exception (#1431). params = dict(secret=recaptcha_private_key, remoteip=client_ip_address, response=recaptcha_response_field.encode('utf8')) response = requests.get(recaptcha_server_name, params) data = response.json() try: if not data['success']: raise CaptchaError() except IndexError: # Something weird with recaptcha response raise CaptchaError()
def tag(id: str) -> Response: data_dict, params = _parse_url_params() data_dict['fq'] = u'tags: "%s"' % id item_count, results = _package_search(data_dict) navigation_urls = _navigation_urls(params, item_count=item_count, limit=data_dict['rows'], controller=u'feeds', action=u'tag', id=id) feed_url = _feed_url(params, controller=u'feeds', action=u'tag', id=id) alternate_url = _alternate_url(params, tags=id) site_title = config.get_value(u'ckan.site_title') title = u'%s - Tag: "%s"' % (site_title, id) desc = u'Recently created or updated datasets on %s by tag: "%s"' % \ (site_title, id) guid = _create_atom_id(u'/feeds/tag/%s.atom' % id) return output_feed(results, feed_title=title, feed_description=desc, feed_link=alternate_url, feed_guid=guid, feed_url=feed_url, navigation_urls=navigation_urls)
def as_dict(self, ref_package_by: str = 'name', ref_group_by: str = 'name') -> dict[str, Any]: _dict = domain_object.DomainObject.as_dict(self) # Set 'license' in _dict to cater for old clients. # Todo: Remove from Version 2? _dict['license'] = self.license.title if self.license else _dict.get( 'license_id', '') _dict['isopen'] = self.isopen() tags = [tag.name for tag in self.get_tags()] tags.sort() # so it is determinable _dict['tags'] = tags groups = [getattr(group, ref_group_by) for group in self.get_groups()] groups.sort() _dict['groups'] = groups _dict['extras'] = {key: value for key, value in self.extras.items()} _dict['resources'] = [res.as_dict(core_columns_only=False) \ for res in self.resources] site_url = config.get_value('ckan.site_url') if site_url: _dict['ckan_url'] = '%s/dataset/%s' % (site_url, self.name) _dict['relationships'] = [ rel.as_dict(self, ref_package_by=ref_package_by) for rel in self.get_relationships() ] _dict['metadata_modified'] = self.metadata_modified.isoformat() \ if self.metadata_modified else None _dict['metadata_created'] = self.metadata_created.isoformat() \ if self.metadata_created else None import ckan.lib.helpers as h _dict['notes_rendered'] = h.render_markdown(self.notes) _dict['type'] = self.type or u'dataset' return _dict
def general() -> Response: data_dict, params = _parse_url_params() data_dict['q'] = u'*:*' item_count, results = _package_search(data_dict) navigation_urls = _navigation_urls(params, item_count=item_count, limit=data_dict['rows'], controller=u'feeds', action=u'general') feed_url = _feed_url(params, controller=u'feeds', action=u'general') alternate_url = _alternate_url(params) guid = _create_atom_id(u'/feeds/dataset.atom') site_title = config.get_value(u'ckan.site_title') desc = u'Recently created or updated datasets on %s' % site_title return output_feed(results, feed_title=site_title, feed_description=desc, feed_link=alternate_url, feed_guid=guid, feed_url=feed_url, navigation_urls=navigation_urls)
def _allow_caching(cache_force: Optional[bool] = None): # Caching Logic allow_cache = True # Force cache or not if explicit. if cache_force is not None: allow_cache = cache_force # Do not allow caching of pages for logged in users/flash messages etc. elif ('user' in g and g.user) or _is_valid_session_cookie_data(): allow_cache = False # Tests etc. elif session.get("_user_id"): allow_cache = False # Don't cache if based on a non-cachable template used in this. elif request.environ.get('__no_cache__'): allow_cache = False # Don't cache if we have set the __no_cache__ param in the query string. elif request.args.get('__no_cache__'): allow_cache = False # Don't cache if caching is not enabled in config elif not config.get_value('ckan.cache_enabled'): allow_cache = False if not allow_cache: # Prevent any further rendering from being cached. request.environ['__no_cache__'] = True