Select Git revision
SecurityConfiguration.java
plugin.py 16.53 KiB
# import from third parties
from dateutil.parser import parse
import json
import logging
from multiline_formatter.formatter import MultilineMessagesFormatter
import os
from routes.mapper import SubMapper
import sys
# imports from ckan
import ckan.lib.helpers as helpers
from ckan.lib.plugins import DefaultTranslation, DefaultDatasetForm
from ckan.logic.validators import tag_string_convert
import ckan.plugins as plugins
import ckan.plugins.toolkit as toolkit
import ckan.model as model
# imports from this extension
import ckanext.odsh.helpers as odsh_helpers
import ckanext.odsh.helpers_tpsh as helpers_tpsh
import ckanext.odsh.helper_pkg_dict as helper_pkg_dict
from .helper_pkg_dict import HelperPgkDict
import ckanext.odsh.logic.action as action
import ckanext.odsh.validation as validation
import ckanext.odsh.search as search
from ckanext.odsh.odsh_logger import OdshLogger
import ckanext.odsh.tools as tools
log = logging.getLogger(__name__)
_ = toolkit._
class OdshPlugin(plugins.SingletonPlugin, DefaultTranslation, DefaultDatasetForm):
plugins.implements(plugins.IActions)
plugins.implements(plugins.IConfigurer)
plugins.implements(plugins.IDatasetForm)
plugins.implements(plugins.IFacets)
plugins.implements(plugins.IPackageController, inherit=True)
plugins.implements(plugins.IRoutes, inherit=True)
plugins.implements(plugins.ITemplateHelpers)
plugins.implements(plugins.ITranslation)
plugins.implements(plugins.IValidators)
plugins.implements(plugins.IResourceController, inherit=True)
# IActions
def get_actions(self):
return {'package_create': action.odsh_package_create,
'user_update':action.tpsh_user_update,
'user_create': action.odsh_user_create,
'resource_create': action.odsh_resource_create,}
# IConfigurer
def update_config(self, config_):
toolkit.add_template_directory(config_, 'templates')
toolkit.add_public_directory(config_, 'public')
toolkit.add_resource('fanstatic', 'odsh')
# IDatasetForm
def package_types(self):
# This plugin doesn't handle any special package types, it just
# registers itself as the default (above).
return []
def is_fallback(self):
# Return True to register this plugin as the default handler for
# package types not handled by any other IDatasetForm plugin.
return True
def create_package_schema(self):
schema = super(OdshPlugin, self).create_package_schema()
self._update_schema(schema)
self._tpsh_update_create_or_update_package_schema(schema)
return schema
def update_package_schema(self):
schema = super(OdshPlugin, self).update_package_schema()
self._update_schema(schema)
self._tpsh_update_create_or_update_package_schema(schema)
return schema
def show_package_schema(self):
schema = super(OdshPlugin, self).show_package_schema()
self._tpsh_update_show_package_schema(schema)
return schema
def _update_schema(self, schema):
for field in ['title', 'license_id']:
schema.update({field: [toolkit.get_converter('not_empty')]})
schema.update({
'reference': [
toolkit.get_validator('ignore_missing'),
toolkit.get_converter('convert_to_extras')
]
})
for i, item in enumerate(schema['tags']['name']):
if item == toolkit.get_validator('tag_name_validator'):
schema['tags']['name'][i] = toolkit.get_validator(
'odsh_tag_name_validator')
for i, item in enumerate(schema['tag_string']):
if item == tag_string_convert:
schema['tag_string'][i] = validation.tag_string_convert
schema['resources'].update({
'url': [toolkit.get_converter('not_empty')],
'format': [toolkit.get_converter('odsh_validate_format')],
})
schema['extras'].update({
'key': [
toolkit.get_converter('known_spatial_uri'),
toolkit.get_converter('validate_licenseAttributionByText'),
]
})
schema.update(
{'__extras': [toolkit.get_converter('odsh_validate_extras')]})
def _tpsh_update_create_or_update_package_schema(self, schema):
schema.update({
'language': [
toolkit.get_validator('ignore_missing'),
toolkit.get_converter('convert_to_extras')
],
'thumbnail': [
toolkit.get_validator('ignore_missing'),
toolkit.get_converter('convert_to_extras')
],
'relatedPackage': [
toolkit.get_validator('tpsh_validate_relatedPackage'),
toolkit.get_converter('convert_to_extras')
],
'accessibility': [
toolkit.get_validator('ignore_missing'),
toolkit.get_converter('convert_to_extras')
]
})
return schema
def _tpsh_update_show_package_schema(self, schema):
schema.update({
'language': [
toolkit.get_converter('convert_from_extras'),
toolkit.get_validator('ignore_missing')
],
'thumbnail': [
toolkit.get_converter('convert_from_extras'),
toolkit.get_validator('ignore_missing')
],
'relatedPackage': [
toolkit.get_converter('convert_from_extras'),
toolkit.get_validator('ignore_missing')
],
'accessibility': [
toolkit.get_converter('convert_from_extras'),
toolkit.get_validator('ignore_missing')
],
})
return schema
# IFacets
def dataset_facets(self, facets_dict, package_type):
return OrderedDict({'organization': _('Herausgeber'),
'groups': _('Kategorie'),
'res_format': _('Dateiformat'),
'license_title': _('Lizenz'),
# 'tags': _('Tags'),
'openness': _('Open-Data-Eigenschaften')
})
def group_facets(self, facets_dict, group_type, package_type):
return OrderedDict({'organization': _('Herausgeber'),
'res_format': _('Dateiformat'),
'license_title': _('Lizenz'),
'groups': _('Kategorie')})
def organization_facets(self, facets_dict, organization_type, package_type):
return OrderedDict({'organization': _('Herausgeber'),
'res_format': _('Dateiformat'),
'license_title': _('Lizenz'),
'groups': _('Kategorie')})
# IPackageController
def after_show(self, context, pkg_dict):
'''
corrects missing relationships in pkg dict
adds the following key-value-pairs to pkg_dict:
# key: 'is_new', value: True if the dataset has been created within the last month
'''
pkg_dict = helpers_tpsh.correct_missing_relationship(
pkg_dict,
helpers_tpsh.get_pkg_relationships_from_model(pkg_dict)
)
self._update_is_new_in_pkg_dict(pkg_dict)
return pkg_dict
def before_view(self, pkg_dict):
'''
adds the following key-value-pairs to pkg_dict:
# key: 'is_new', value: True if the dataset has been created within the last month
'''
self._update_is_new_in_pkg_dict(pkg_dict)
return pkg_dict
def after_create(self, context, resource):
if resource.get('package_id'):
tools.add_attributes_resources(context, resource)
def after_update(self, context, resource):
if resource.get('package_id'):
tools.add_attributes_resources(context, resource)
@staticmethod
def _update_is_new_in_pkg_dict(pkg_dict):
is_new = HelperPgkDict(pkg_dict).is_package_new()
pkg_dict.update({'is_new': is_new})
def before_index(self, dict_pkg):
# make special date fields solr conform
fields = ["issued", "temporal_start", "temporal_end"]
for field in fields:
field = 'extras_' + field
if field in dict_pkg and dict_pkg[field]:
d = parse(dict_pkg[field])
dict_pkg[field] = '{0.year:04d}-{0.month:02d}-{0.day:02d}T00:00:00Z'.format(
d)
self.map_qa_score(dict_pkg)
return dict_pkg
# IRoutes
def before_map(self, map):
map.connect(
'info_page',
'/info_page',
controller='ckanext.odsh.controller:OdshRouteController',
action='info_page'
)
map.connect(
'home',
'/',
controller='ckanext.odsh.controller:OdshRouteController',
action='start'
)
map.redirect('/dataset/{id}/resource/{resource_id}', '/dataset/{id}')
if plugins.toolkit.asbool(tk.config.get('ckanext.dcat.enable_rdf_endpoints', True)):
odsh_helpers.odsh_remove_route(map, 'dcat_catalog')
map.connect(
'dcat_catalog',
tk.config.get(
'ckanext.dcat.catalog_endpoint',
'/catalog.{_format}'
),
controller='ckanext.odsh.controller:OdshDCATController',
action='read_catalog',
requirements={'_format': 'xml|rdf|n3|ttl|jsonld'}
)
# /api ver 3 or none with matomo
GET_POST = dict(method=['GET', 'POST'])
with SubMapper(
map,
controller='ckanext.odsh.controller:OdshApiController',
path_prefix='/api{ver:/3|}',
ver='/3'
) as m:
m.connect('/action/{logic_function}',
action='action', conditions=GET_POST)
with SubMapper(map, controller='ckanext.odsh.controller:OdshFeedController') as m:
m.connect('/feeds/custom.atom', action='custom')
with SubMapper(map, controller='ckanext.odsh.controller:OdshPackageController') as m:
m.connect('new_view', '/dataset/{id}/resource/{resource_id}/new_view',
action='edit_view', ckan_icon='pencil-square-o')
with SubMapper(map, controller='ckanext.odsh.controller:OdshGroupController') as m:
m.connect('organizations_index', '/organization', action='index')
# redirect all user routes to custom controller
with SubMapper(map, controller='ckanext.odsh.controller:OdshUserController') as m:
m.connect('user_index', '/user', action='index')
m.connect('/user/edit', action='edit')
m.connect(
'user_edit', '/user/edit/{id:.*}', action='edit', ckan_icon='cog')
m.connect('user_delete', '/user/delete/{id}', action='delete')
m.connect('/user/reset/{id:.*}', action='perform_reset')
m.connect('/user/reset', action='request_reset')
m.connect('register', '/user/register', action='register')
m.connect('login', '/user/login', action='login')
m.connect('/user/_logout', action='logout')
m.connect('/user/logged_in', action='logged_in')
m.connect('/user/logged_out', action='logged_out')
m.connect('/user/logged_out_redirect', action='logged_out_page')
m.connect('user_datasets', '/user/{id:(?!(generate_key|activity)).*}', action='read',
ckan_icon='sitemap')
map.connect(
'comment_datarequest',
'/datarequest/new',
controller='ckanext.datarequests.controllers.ui_controller:DataRequestsUI',
action='new',
conditions=dict(method=['GET', 'POST']),
ckan_icon='comment'
)
map.connect(
'comment_datarequest',
'/datarequest/{id}',
controller='ckanext.datarequests.controllers.ui_controller:DataRequestsUI',
action='comment',
conditions=dict(method=['GET', 'POST']),
ckan_icon='comment'
)
return map
def after_map(self, map):
return map
# ITemplateHelpers
def get_helpers(self):
# Template helper function names should begin with the name of the
# extension they belong to, to avoid clashing with functions from
# other extensions.
return {
'odsh_main_groups': odsh_helpers.odsh_main_groups,
'odsh_now': odsh_helpers.odsh_now,
'odsh_group_id_selected': odsh_helpers.odsh_group_id_selected,
'odsh_get_facet_items_dict': odsh_helpers.odsh_get_facet_items_dict,
'odsh_openness_score_dataset_html': odsh_helpers.odsh_openness_score_dataset_html,
'odsh_get_resource_details': odsh_helpers.odsh_get_resource_details,
'odsh_get_resource_views': odsh_helpers.odsh_get_resource_views,
'odsh_get_bounding_box': odsh_helpers.odsh_get_bounding_box,
'odsh_get_spatial_text': odsh_helpers.odsh_get_spatial_text,
'odsh_render_datetime': odsh_helpers.odsh_render_datetime,
'odsh_upload_known_formats': odsh_helpers.odsh_upload_known_formats,
'odsh_encodeurl': odsh_helpers.odsh_encodeurl,
'odsh_extract_error': odsh_helpers.odsh_extract_error,
'odsh_extract_error_new': odsh_helpers.odsh_extract_error_new,
'odsh_extract_value_from_extras': odsh_helpers.odsh_extract_value_from_extras,
'odsh_create_checksum': odsh_helpers.odsh_create_checksum,
'presorted_license_options': odsh_helpers.presorted_license_options,
'odsh_tracking_id': odsh_helpers.odsh_tracking_id,
'odsh_tracking_url': odsh_helpers.odsh_tracking_url,
'odsh_has_more_facets': odsh_helpers.odsh_has_more_facets,
'odsh_public_url': odsh_helpers.odsh_public_url,
'odsh_spatial_extends_available': odsh_helpers.spatial_extends_available,
'odsh_public_resource_url': odsh_helpers.odsh_public_resource_url,
'odsh_get_version_id': odsh_helpers.odsh_get_version_id,
'odsh_show_testbanner': odsh_helpers.odsh_show_testbanner,
'odsh_is_slave': odsh_helpers.odsh_is_slave,
'odsh_use_matomo': helpers_tpsh.use_matomo,
'tpsh_get_daterange_prettified': helper_pkg_dict.get_daterange_prettified,
'tpsh_get_language_of_package': helpers_tpsh.get_language_of_package,
'get_language_icon': helpers_tpsh.get_language_icon,
'short_name_for_category': odsh_helpers.short_name_for_category,
'get_spatial_for_selection': helpers_tpsh.get_spatial_for_selection,
'get_subject_for_selection': helpers_tpsh.get_subject_for_selection,
'get_language_for_selection': helpers_tpsh.get_language_for_selection,
'tpsh_get_resource_size': helpers_tpsh.get_resource_size,
'tpsh_get_address_org':helpers_tpsh.get_address_org,
'tpsh_get_body_mail':helpers_tpsh.get_body_mail,
'odsh_load_mdk_sample_dataset': odsh_helpers.odsh_load_mdk_sample_dataset,
'odsh_load_raw_mdk_sample_dataset': odsh_helpers.odsh_load_raw_mdk_sample_dataset,
}
# IValidators
def get_validators(self):
return validation.get_validators()
# Add the custom parameters to Solr's facet queries
# use several daterange queries agains temporal_start and temporal_end field
# TODO: use field of type date_range in solr index instead
def before_search(self, search_params):
return search.before_search(search_params)
scores = [['0OL'], ['0OL', '1RE'], ['0OL', '1RE', '2OF'], [
'0OL', '1RE', '2OF', '3URI'], ['0OL', '1RE', '2OF', '3URI', '4LD']]
def map_qa_score(self, dict_pkg):
if 'validated_data_dict' in dict_pkg and 'openness_score' in dict_pkg['validated_data_dict']:
d = json.loads(dict_pkg['validated_data_dict'])
score = -1
for r in d['resources']:
if 'qa' in r:
i = r['qa'].find('openness_score')
s = int(r['qa'][i+17])
if s > score:
score = s
if score > 0:
dict_pkg['openness'] = OdshPlugin.scores[score-1]