def dictionary(self, id, resource_id): u'''data dictionary view: show/edit field labels and descriptions''' try: # resource_edit_base template uses these c.pkg_dict = get_action('package_show')(None, {'id': id}) c.resource = get_action('resource_show')(None, {'id': resource_id}) rec = get_action('datastore_search')(None, { 'resource_id': resource_id, 'limit': 0 }) except (ObjectNotFound, NotAuthorized): abort(404, _('Resource not found')) fields = [f for f in rec['fields'] if not f['id'].startswith('_')] if request.method == 'POST': data = dict_fns.unflatten( tuplize_dict(parse_params(request.params))) info = data.get(u'info') if not isinstance(info, list): info = [] info = info[:len(fields)] get_action('datastore_create')(None, { 'resource_id': resource_id, 'force': True, 'fields': [{ 'id': f['id'], 'type': f['type'], 'info': fi if isinstance(fi, dict) else {} } for f, fi in izip_longest(fields, info)] }) h.flash_success( _('Data Dictionary saved. Any type overrides will ' 'take effect when the resource is next uploaded ' 'to DataStore')) h.redirect_to( controller='ckanext.datastore.controller:DatastoreController', action='dictionary', id=id, resource_id=resource_id) return render('datastore/dictionary.html', extra_vars={ 'fields': fields, 'pkg_dict': c.pkg_dict, 'resource': c.resource, })
def geocoded_data(self, id, resource_id): u'''geocoded data fields view: show/edit geocoded data fields''' try: # resource_edit_base template uses these c.pkg_dict = get_action('package_show')( None, {'id': id}) c.resource = get_action('resource_show')( None, {'id': resource_id}) rec = get_action('datastore_search')(None, { 'resource_id': resource_id, 'limit': 0}) except (ObjectNotFound, NotAuthorized): abort(404, _('Resource not found')) fields = get_geocoded_fields() resource_fields = rec.get('fields') address_column_options = [{"text":"","value":""}] for resource_field in resource_fields: if resource_field.get('id') == '_id': continue address_column_options.append({"text":resource_field.get('id'),"value":resource_field.get('id')}) if request.method == 'POST': data = dict(request.POST) for field in fields: key = field.get('field_name') value = data.get(key) if ResourceGeocodeData.exists(resource_id=resource_id,key=key): gecodefield_obj = ResourceGeocodeData.get(resource_id=resource_id,key=key) gecodefield_obj.value = value gecodefield_obj.commit() else: ResourceGeocodeData.create(resource_id=resource_id,key=key, value=value) maybe_schedule(c.resource) h.redirect_to( controller='ckanext.geocodejob.controller:GeocodejobController', action='geocoded_data', id=id, resource_id=resource_id) geocode_data_values = ResourceGeocodeData.get_geocode_data_values(resource_id) return render( 'package/geocoded_data.html', extra_vars={'fields': fields, 'address_column_options':address_column_options, 'geocode_data_values':geocode_data_values})
def dictionary(self, id, resource_id): u'''data dictionary view: show/edit field labels and descriptions''' try: # resource_edit_base template uses these c.pkg_dict = get_action('package_show')( None, {'id': id}) c.resource = get_action('resource_show')( None, {'id': resource_id}) rec = get_action('datastore_search')(None, { 'resource_id': resource_id, 'limit': 0}) except (ObjectNotFound, NotAuthorized): abort(404, _('Resource not found')) fields = [f for f in rec['fields'] if not f['id'].startswith('_')] if request.method == 'POST': data = dict_fns.unflatten(tuplize_dict(parse_params( request.params))) info = data.get(u'info') if not isinstance(info, list): info = [] info = info[:len(fields)] get_action('datastore_create')(None, { 'resource_id': resource_id, 'force': True, 'fields': [{ 'id': f['id'], 'type': f['type'], 'info': fi if isinstance(fi, dict) else {} } for f, fi in izip_longest(fields, info)]}) h.flash_success(_('Data Dictionary saved. Any type overrides will ' 'take effect when the resource is next uploaded ' 'to DataStore')) h.redirect_to( controller='ckanext.datastore.controller:DatastoreController', action='dictionary', id=id, resource_id=resource_id) return render( 'datastore/dictionary.html', extra_vars={ 'fields': fields, 'pkg_dict': c.pkg_dict, 'resource': c.resource, })
def post(self, id, resource_id): u'''Data dictionary view: edit field labels and descriptions''' data_dict = self._prepare(id, resource_id) fields = data_dict[u'fields'] data = dict_fns.unflatten(tuplize_dict(parse_params(request.form))) info = data.get(u'info') if not isinstance(info, list): info = [] info = info[:len(fields)] get_action(u'datastore_create')( None, { u'resource_id': resource_id, u'force': True, u'fields': [{ u'id': f[u'id'], u'type': f[u'type'], u'info': fi if isinstance(fi, dict) else {} } for f, fi in zip_longest(fields, info)] } ) h.flash_success( _( u'Data Dictionary saved. Any type overrides will ' u'take effect when the resource is next uploaded ' u'to DataStore' ) ) return h.redirect_to( u'datastore.dictionary', id=id, resource_id=resource_id )
def filtered_download(resource_view_id): params = json.loads(request.form[u'params']) resource_view = get_action(u'resource_view_show')(None, { u'id': resource_view_id }) search_text = text_type(params[u'search'][u'value']) view_filters = resource_view.get(u'filters', {}) user_filters = text_type(params[u'filters']) filters = merge_filters(view_filters, user_filters) datastore_search = get_action(u'datastore_search') unfiltered_response = datastore_search( None, { u"resource_id": resource_view[u'resource_id'], u"limit": 0, u"filters": view_filters, }) cols = [f[u'id'] for f in unfiltered_response[u'fields']] if u'show_fields' in resource_view: cols = [c for c in cols if c in resource_view[u'show_fields']] sort_list = [] for order in params[u'order']: sort_by_num = int(order[u'column']) sort_order = (u'desc' if order[u'dir'] == u'desc' else u'asc') sort_list.append(cols[sort_by_num] + u' ' + sort_order) cols = [c for (c, v) in zip(cols, params[u'visible']) if v] colsearch_dict = {} columns = params[u'columns'] for column in columns: if column[u'search'][u'value']: v = column[u'search'][u'value'] if v: k = column[u'name'] # replace non-alphanumeric characters with FTS wildcard (_) v = re.sub(r'[^0-9a-zA-Z\-]+', '_', v) # append ':*' so we can do partial FTS searches colsearch_dict[k] = v + u':*' if colsearch_dict: search_text = json.dumps(colsearch_dict) else: search_text = re.sub(r'[^0-9a-zA-Z\-]+', '_', search_text) + u':*' if search_text else '' return h.redirect_to( h.url_for(u'datastore.dump', resource_id=resource_view[u'resource_id']) + u'?' + urlencode({ u'q': search_text, u'plain': False, u'language': u'simple', u'sort': u','.join(sort_list), u'filters': json.dumps(filters), u'format': request.form[u'format'], u'fields': u','.join(cols), }))
def delete(content_type, content_item_id, comment_id): 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) try: data_dict = { 'id': comment_id, 'content_type': content_type, 'content_item_id': content_item_id } get_action('comment_delete')(context, data_dict) except Exception as e: log.debug(e) if e.error_dict and e.error_dict.get('message'): msg = e.error_dict['message'] else: msg = str(e) h.flash_error(msg) return h.redirect_to( helpers.get_redirect_url( content_type, content_item_id if content_type == 'datarequest' else c.pkg.name, 'comment_' + str(comment_id)))
def filtered_download(self, resource_view_id): params = json.loads(request.params['params']) resource_view = get_action(u'resource_view_show')( None, { u'id': resource_view_id }) search_text = text_type(params['search']['value']) view_filters = resource_view.get(u'filters', {}) user_filters = text_type(params['filters']) filters = merge_filters(view_filters, user_filters) datastore_search = get_action(u'datastore_search') unfiltered_response = datastore_search( None, { u"resource_id": resource_view[u'resource_id'], u"limit": 0, u"filters": view_filters, }) cols = [f['id'] for f in unfiltered_response['fields']] if u'show_fields' in resource_view: cols = [c for c in cols if c in resource_view['show_fields']] sort_list = [] for order in params['order']: sort_by_num = int(order['column']) sort_order = (u'desc' if order['dir'] == u'desc' else u'asc') sort_list.append(cols[sort_by_num] + u' ' + sort_order) cols = [c for (c, v) in zip(cols, params['visible']) if v] h.redirect_to( h.url_for( controller=u'ckanext.datastore.controller:DatastoreController', action=u'dump', resource_id=resource_view[u'resource_id']) + u'?' + urlencode({ u'q': search_text, u'sort': u','.join(sort_list), u'filters': json.dumps(filters), u'format': request.params['format'], u'fields': u','.join(cols), }))
def filtered_download(self, resource_view_id): params = json.loads(request.params['params']) resource_view = get_action(u'resource_view_show')( None, {u'id': resource_view_id}) search_text = text_type(params['search']['value']) view_filters = resource_view.get(u'filters', {}) user_filters = text_type(params['filters']) filters = merge_filters(view_filters, user_filters) datastore_search = get_action(u'datastore_search') unfiltered_response = datastore_search(None, { u"resource_id": resource_view[u'resource_id'], u"limit": 0, u"filters": view_filters, }) cols = [f['id'] for f in unfiltered_response['fields']] if u'show_fields' in resource_view: cols = [c for c in cols if c in resource_view['show_fields']] sort_list = [] for order in params['order']: sort_by_num = int(order['column']) sort_order = ( u'desc' if order['dir'] == u'desc' else u'asc') sort_list.append(cols[sort_by_num] + u' ' + sort_order) cols = [c for (c, v) in zip(cols, params['visible']) if v] h.redirect_to( h.url_for( controller=u'ckanext.datastore.controller:DatastoreController', action=u'dump', resource_id=resource_view[u'resource_id']) + u'?' + urlencode({ u'q': search_text, u'sort': u','.join(sort_list), u'filters': json.dumps(filters), u'format': request.params['format'], u'fields': u','.join(cols), }))
def dictionary(self, id, resource_id): u'''data dictionary view: show/edit field labels and descriptions''' try: # resource_edit_base template uses these c.pkg_dict = get_action('package_show')(None, {'id': id}) c.resource = get_action('resource_show')(None, {'id': resource_id}) rec = get_action('datastore_search')(None, { 'resource_id': resource_id, 'limit': 0 }) except (ObjectNotFound, NotAuthorized): abort(404, _('Resource not found')) fields = [f for f in rec['fields'] if not f['id'].startswith('_')] if request.method == 'POST': get_action('datastore_create')(None, { 'resource_id': resource_id, 'force': True, 'fields': [{ 'id': f['id'], 'type': f['type'], 'info': { 'label': request.POST.get('f{0}label'.format(i)), 'notes': request.POST.get('f{0}notes'.format(i)), } } for i, f in enumerate(fields, 1)] }) h.redirect_to( controller='ckanext.datastore.controller:DatastoreController', action='dictionary', id=id, resource_id=resource_id) return render('datastore/dictionary.html', extra_vars={'fields': fields})
def unflag(content_type, content_item_id, comment_id): """ Remove the 'flagged' attribute on a comment :param content_type: string 'dataset' or 'datarequest' :param content_item_id: string :param comment_id: string ID of the comment to unflag :return: """ context = {'model': model, 'user': c.user} # Using the comment model rather than the update action because update action updates modified timestamp comment = comment_model.Comment.get(comment_id) if not comment \ or not comment.flagged \ or not authz.auth_is_loggedin_user() \ or not helpers.user_can_manage_comments(content_type, content_item_id): abort(403) comment.flagged = False model.Session.add(comment) model.Session.commit() h.flash_success(_('Comment un-flagged')) data_dict = {'id': content_item_id} if content_type == 'datarequest': c.datarequest = get_action('show_datarequest')(context, data_dict) return h.redirect_to( str('/datarequest/comment/%s#comment_%s' % (content_item_id, comment_id))) else: c.pkg_dict = get_action('package_show')(context, data_dict) c.pkg = context['package'] return h.redirect_to( str('/dataset/%s#comment_%s' % (content_item_id, comment_id))) return helpers.render_content_template(content_type)
def post(self, dataset_id, resource_id, id): context = {'model': model, 'session': model.Session, 'user': c.user} try: get_action('resource_acl_delete')(context, {'id': id}) h.flash_notice(_('Resource ACL has been deleted.')) return h.redirect_to( 'resourceauthorizer.resource_acl', dataset_id=dataset_id, resource_id=resource_id ) except NotAuthorized: abort(403) except NotFound: abort(404)
def edit(content_type, content_item_id, comment_id): 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['id'] = comment_id data_dict['content_type'] = content_type data_dict['content_item_id'] = content_item_id success = False try: get_action('comment_update')(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) return h.redirect_to( helpers.get_redirect_url( content_type, content_item_id if content_type == 'datarequest' else c.pkg.name, 'comment_' + str(comment_id) if success else 'edit_' + str(comment_id))) return helpers.render_content_template(content_type)
def _redirect_to_this_controller(self, *args, **kw): kw['controller'] = request.environ['pylons.routes_dict']['controller'] return h.redirect_to(*args, **kw)
def post(self, dataset_id, resource_id): context = {'model': model, 'session': model.Session, 'user': c.user} try: check_access('resource_acl_create', context, { 'resource_id': resource_id }) except NotAuthorized: abort(403, _('Unauthorized to create resource acl %s') % '') try: pkg_dict = get_action('package_show')(None, {'id': dataset_id}) resource = get_action('resource_show')(None, {'id': resource_id}) permissions = [{ 'text': u'None', 'value': 'none' }, { 'text': u'Read', 'value': 'read' }] data_dict = clean_dict( dict_fns.unflatten( tuplize_dict(parse_params(request.form)))) acl = data_dict.get('id') if acl is None: data = { 'resource_id': resource_id, 'permission': data_dict['permission'] } if data_dict['organization']: group = model.Group.get(data_dict['organization']) if not group: message = _(u'Organization {org} does not exist.').format( org=data_dict['organization']) raise ValidationError( { 'message': message }, error_summary=message) data['auth_type'] = 'org' data['auth_id'] = group.id elif data_dict['username']: user = model.User.get(data_dict['username']) if not user: message = _(u'User {username} does not exist.').format( username=data_dict['username']) raise ValidationError( { 'message': message }, error_summary=message) data['auth_type'] = 'user' data['auth_id'] = user.id get_action('resource_acl_create')(None, data) else: data = {'id': acl, 'permission': data_dict['permission']} get_action('resource_acl_patch')(None, data) return h.redirect_to( 'resourceauthorizer.resource_acl', dataset_id=dataset_id, resource_id=resource_id ) except NotAuthorized: abort(403) except NotFound: abort(404) except ValidationError as e: h.flash_error(e.error_summary)
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)