def commitments(self, id): """ Shows all of the commitments for the specified publisher """ from ckanext.dgu.model.commitment import Commitment context = { 'model': model, 'session': model.Session, 'user': c.user or c.author, 'extras_as_string': True, 'save': 'save' in request.params } try: c.publisher_dict = get_action('organization_show')(context, { 'id': id }) except NotAuthorized: abort(401, _('Unauthorized to read commitments')) except ObjectNotFound: abort(404, _('Publisher not found')) c.publisher = context.get('group') c.commitments = Commitment.get_for_publisher(c.publisher.name)\ .order_by('commitment.dataset_name').all() return render('commitment/read.html')
def delete(self, id): """Provide a delete action, but only for UKLP datasets""" from ckan.lib.search import SearchIndexError context = { 'model': model, 'session': model.Session, 'user': c.user, } pkg_dict = get_action('package_show')(context, { 'id': id }) # has side-effect of populating context.get('package') if request.params: # POST if 'cancel' in request.params: h.redirect_to(controller='package', action='read', id=id) elif 'delete' in request.params: try: package_name = pkg_dict['name'] get_action('package_delete')(context, {'id': id}) h.flash_success(_('Successfully deleted package.')) self._form_save_redirect(package_name, 'edit') except NotAuthorized: abort(401, _('Unauthorized to delete package %s') % id) except ObjectNotFound, e: abort(404, _('Package not found')) except DataError: abort(400, _(u'Integrity Error')) except SearchIndexError, e: abort(500, _(u'Unable to update search index.') + repr(e.args))
def delete(self, id): """Provide a delete action, but only for UKLP datasets""" from ckan.lib.search import SearchIndexError context = { 'model': model, 'session': model.Session, 'user': c.user, } pkg_dict = get_action('package_show')(context, {'id':id}) # has side-effect of populating context.get('package') if request.params: # POST if 'cancel' in request.params: h.redirect_to(controller='package', action='read', id=id) elif 'delete' in request.params: try: package_name = pkg_dict['name'] get_action('package_delete')(context, {'id':id}) h.flash_success(_('Successfully deleted package.')) self._form_save_redirect(package_name, 'edit') except NotAuthorized: abort(401, _('Unauthorized to delete package %s') % id) except ObjectNotFound, e: abort(404, _('Package not found')) except DataError: abort(400, _(u'Integrity Error')) except SearchIndexError, e: abort(500, _(u'Unable to update search index.') + repr(e.args))
def edit_item(self, id, data=None, errors=None, error_summary=None): """ Allows for the editing of a single item """ context = {'model': model, 'session': model.Session, 'user': c.user or c.author, 'extras_as_string': True, 'save': 'save' in request.params} if context['save'] and not data: return self._save_edit(id, context) try: c.pkg_dict = get_action('package_show')(context, {'id': id}) context['for_edit'] = True old_data = get_action('package_show')(context, {'id': id}) # old data is from the database and data is passed from the # user if there is a validation error. Use users data if there. data = data or old_data except NotAuthorized: abort(401, _('Unauthorized to read package %s') % '') except ObjectNotFound: abort(404, _('Dataset not found')) c.pkg = context.get("package") try: check_access('package_update',context) except NotAuthorized, e: abort(401, _('User %r not authorized to edit %s') % (c.user, id))
def index(self): context = {'model': model, 'session': model.Session, 'user': c.user or c.author} data_dict = {'all_fields': True} try: check_access('site_read', context) except NotAuthorized: abort(401, _('Not authorized to see this page')) # TODO: Fix this up, we only really need to do this when we are # showing the hierarchy (and then we should load on demand really). c.all_groups = model.Session.query(model.Group).\ filter(model.Group.type == 'publisher').\ filter(model.Group.state == 'active').\ order_by('title') c.page = AlphaPage( controller_name="ckanext.dgu.controllers.publisher:PublisherController", collection=c.all_groups, page=request.params.get('page', 'A'), alpha_attribute='title', other_text=_('Other'), ) return render('publisher/index.html')
def _send_application( self, group, reason ): from ckan.logic.action import error_summary from ckan.lib.mailer import mail_recipient from genshi.template.text import NewTextTemplate from pylons import config if not reason: h.flash_error(_("There was a problem with your submission, \ please correct it and try again")) errors = {"reason": ["No reason was supplied"]} return self.apply(group.id, errors=errors, error_summary=error_summary(errors)) # look for publisher admins up the tree recipients = [] recipient_publisher = None for publisher in go_up_tree(group): admins = publisher.members_of_type(model.User, 'admin').all() if admins: recipients = [(u.fullname,u.email) for u in admins] recipient_publisher = publisher.title break if not recipients: if not config.get('dgu.admin.email'): log.error('User "%s" prevented from applying for publisher access for "%s" ' 'because: dgu.admin.email is not setup in CKAN config.', c.user, group.name) h.flash_error(_("There is a problem with the system configuration")) errors = {"reason": ["%s does not have an administrator user to contact" % group.name]} return self.apply(group.id, data=data, errors=errors, error_summary=error_summary(errors)) recipients = [(config.get('dgu.admin.name', "DGU Admin"), config['dgu.admin.email'])] recipient_publisher = 'data.gov.uk admin' log.debug('User "%s" requested publisher access for "%s" which was sent to admin %s (%r) with reason: %r', c.user, group.name, recipient_publisher, recipients, reason) extra_vars = { 'group' : group, 'requester': c.userobj, 'reason' : reason } email_msg = render("email/join_publisher_request.txt", extra_vars=extra_vars, loader_class=NewTextTemplate) try: for (name,recipient) in recipients: mail_recipient(name, recipient, "Publisher request", email_msg) except Exception, e: h.flash_error(_("There is a problem with the system configuration")) errors = {"reason": ["No mail server was found"]} log.error('User "%s" prevented from applying for publisher access for "%s" because of mail configuration error: %s', c.user, group.name, e) return self.apply(group.id, errors=errors, error_summary=error_summary(errors))
def index(self): c.q = request.params.get('q', '') context = { 'model': model, 'session': model.Session, 'user': c.user or c.author, 'for_view': True } # This is the one difference from ckan core. # No need for all vocab / translation stuff, so save the massive # effort of dictizing every tag. This improves page load from # 60s to 10s. data_dict = {'all_fields': False} if c.q: try: page = int(request.params.get('page', 1)) except ValueError: abort(404, _('Not found')) data_dict['q'] = c.q data_dict['limit'] = LIMIT data_dict['offset'] = (page - 1) * LIMIT data_dict['return_objects'] = True result_dict = get_action('tag_search')(context, data_dict) def pager_url(q=None, page=None): return h.url_for( controller='ckanext.dgu.controllers.tag:TagController', action='index', q=request.params['q'], page=page) c.page = h.Page( collection=result_dict['results'], page=page, item_count=result_dict['count'], items_per_page=LIMIT, url=pager_url, ) c.page.items = [ tag_dict['name'] for tag_dict in result_dict['results'] ] else: results = get_action('tag_list')(context, data_dict) c.page = AlphaPageLarge( collection=results, page=request.params.get('page', 'A'), alpha_attribute='name', other_text=_('Other'), controller_name='ckanext.dgu.controllers.tag:TagController', ) return render('tag/index.html')
def index(self): c.q = request.params.get("q", "") context = {"model": model, "session": model.Session, "user": c.user or c.author, "for_view": True} # This is the one difference from ckan core. # No need for all vocab / translation stuff, so save the massive # effort of dictizing every tag. This improves page load from # 60s to 10s. data_dict = {"all_fields": False} if c.q: try: page = int(request.params.get("page", 1)) except ValueError: abort(404, _("Not found")) data_dict["q"] = c.q data_dict["limit"] = LIMIT data_dict["offset"] = (page - 1) * LIMIT data_dict["return_objects"] = True result_dict = get_action("tag_search")(context, data_dict) def pager_url(q=None, page=None): return h.url_for( controller="ckanext.dgu.controllers.tag:TagController", action="index", q=request.params["q"], page=page, ) c.page = h.Page( collection=result_dict["results"], page=page, item_count=result_dict["count"], items_per_page=LIMIT, url=pager_url, ) c.page.items = [tag_dict["name"] for tag_dict in result_dict["results"]] else: results = get_action("tag_list")(context, data_dict) c.page = AlphaPageLarge( collection=results, page=request.params.get("page", "A"), alpha_attribute="name", other_text=_("Other"), controller_name="ckanext.dgu.controllers.tag:TagController", ) return render("tag/index.html")
def users(self, id, data=None, errors=None, error_summary=None): c.group = model.Group.get(id) if not c.group: abort(404, _('Group not found')) context = { 'model': model, 'session': model.Session, 'user': c.user or c.author, 'group': c.group } try: check_access('group_update',context) except NotAuthorized, e: abort(401, _('User %r not authorized to edit %s') % (c.user, id))
def apply(self, id=None, data=None, errors=None, error_summary=None): """ Form for a user to request to be an editor for a publisher. It sends an email to a suitable admin. """ if 'parent' in request.params and not id: id = request.params['parent'] if id: c.group = model.Group.get(id) if not c.group: abort(404, _('Publisher not found')) if 'save' in request.params and not errors: return self._send_application(c.group, request.params.get('reason', None)) self._add_publisher_list() data = data or {} errors = errors or {} error_summary = error_summary or {} data.update(request.params) vars = {'data': data, 'errors': errors, 'error_summary': error_summary} c.form = render('publisher/apply_form.html', extra_vars=vars) return render('publisher/apply.html')
def __before__(self, action, **env): try: BaseController.__before__(self, action, **env) except NotAuthorized: abort(401, _('Not authorized to see this page')) except (sqlalchemy.exc.ProgrammingError, sqlalchemy.exc.OperationalError), e: # postgres and sqlite errors for missing tables msg = str(e) if ('relation' in msg and 'does not exist' in msg) or \ ('no such table' in msg) : # table missing, major database problem abort(503, _('This site is currently off-line. Database is not initialised.')) # TODO: send an email to the admin person (#1285) else: raise
def delete(self, id): """Provide a delete ('withdraw') action, but only for UKLP datasets""" from ckan.lib.search import SearchIndexError context = { 'model': model, 'session': model.Session, 'user': c.user, } try: pkg_dict = get_action('package_show')(context, { 'id': id }) # has side-effect of populating context.get('package') except NotAuthorized: abort(401, 'Not authorized to delete package') except ObjectNotFound: abort(404, 'Dataset not found') if request.params: # POST if 'cancel' in request.params: h.redirect_to(controller='package', action='read', id=id) elif 'delete' in request.params: try: package_name = pkg_dict['name'] get_action('package_delete')(context, {'id': id}) is_uklp = get_from_flat_dict(pkg_dict['extras'], 'UKLP') == 'True' if is_uklp: action = 'withdrawn' resource_type = get_from_flat_dict( pkg_dict['extras'], 'resource-type') + ' record' else: action = 'deleted' resource_type = 'dataset' h.flash_success('Successfully %s %s.' \ % (action, resource_type)) self._form_save_redirect(package_name, 'edit') except NotAuthorized: abort(401, _('Unauthorized to delete package %s') % id) except ObjectNotFound, e: abort(404, _('Package not found')) except DataError: abort(400, _(u'Integrity Error')) except SearchIndexError, e: abort(500, _(u'Unable to update search index.') + repr(e.args))
def _get_package(self, id): """ Given an ID use the logic layer to fetch the Package and a dict representation of it as well as adding formatted notes and the publisher to the template context (c). """ import ckan.misc import genshi context = { 'model': model, 'session': model.Session, 'user': c.user or c.author, 'extras_as_string': True, 'for_view': True } try: c.pkg_dict = get_action('package_show')(context, {'id': id}) c.pkg = context['package'] except ObjectNotFound: abort(404, _('Dataset not found')) except NotAuthorized: abort(401, _('Unauthorized to read package %s') % id) groups = c.pkg.get_groups('publisher') if groups: c.publisher = groups[0] else: log.warning("Package {0} is not a member of any group!".format(id)) # Try and render the notes as markdown for display on the page. Most # unpublished items *won't* be markdown if they've come directly from the # CSV - unless they've been edited. try: notes_formatted = ckan.misc.MarkdownFormat().to_html(c.pkg.notes) c.pkg_notes_formatted = genshi.HTML(notes_formatted) c.release_notes_formatted = None notes = unpublished_release_notes(c.pkg_dict) if notes and notes.strip(): c.release_notes_formatted = genshi.HTML( ckan.misc.MarkdownFormat().to_html(notes)) except Exception: c.pkg_notes_formatted = c.pkg.notes
class PackageController(ckan.controllers.package.PackageController): def __before__(self, action, **params): super(PackageController, self).__before__(action, **params) c.all_resources = 'all' in request.params.keys() def history(self, id): """ Auth is different for DGU than for publisher default """ # TODO Replace user names with department names return super(PackageController, self).history(id) def delete(self, id): """Provide a delete ('withdraw') action, but only for UKLP datasets""" from ckan.lib.search import SearchIndexError context = { 'model': model, 'session': model.Session, 'user': c.user, } try: pkg_dict = get_action('package_show')(context, { 'id': id }) # has side-effect of populating context.get('package') except NotAuthorized: abort(401, 'Not authorized to delete package') if request.params: # POST if 'cancel' in request.params: h.redirect_to(controller='package', action='read', id=id) elif 'delete' in request.params: try: package_name = pkg_dict['name'] get_action('package_delete')(context, {'id': id}) is_uklp = get_from_flat_dict(pkg_dict['extras'], 'UKLP') == 'True' if is_uklp: action = 'withdrawn' resource_type = get_from_flat_dict( pkg_dict['extras'], 'resource-type') + ' record' else: action = 'deleted' resource_type = 'dataset' h.flash_success('Successfully %s %s.' \ % (action, resource_type)) self._form_save_redirect(package_name, 'edit') except NotAuthorized: abort(401, _('Unauthorized to delete package %s') % id) except ObjectNotFound, e: abort(404, _('Package not found')) except DataError: abort(400, _(u'Integrity Error')) except SearchIndexError, e: abort(500, _(u'Unable to update search index.') + repr(e.args)) except ValidationError, e: abort(400, _('Unable to delete package.') + repr(e.error_dict))
def __before__(self, action, **env): try: BaseController.__before__(self, action, **env) except NotAuthorized: abort(401, _('Not authorized to see this page')) except (sqlalchemy.exc.ProgrammingError, sqlalchemy.exc.OperationalError), e: # postgres and sqlite errors for missing tables msg = str(e) if ('relation' in msg and 'does not exist' in msg) or \ ('no such table' in msg) : # table missing, major database problem abort( 503, _('This site is currently off-line. Database is not initialised.' )) # TODO: send an email to the admin person (#1285) else: raise
def contact(self, name=None): """ This action allows users to create an issue by filling in a contact form. """ import ckan.model as model from ckanext.redmine.client import RedmineClient print name extra_vars = {"data": {}, "errors": {}} client = RedmineClient(name) c.categories = client.load_categories() c.name = name if request.method == 'POST': data = clean_dict( unflatten(tuplize_dict(parse_params(request.POST)))) context = { 'model': model, 'session': model.Session, 'user': c.user } # Create the issue with the data we were passed. try: newid = get_action('issue_create')(context, data) if newid is None: self._save_on_fail(data) h.flash_success( _('Thank you for contacting us'.format(newid))) else: h.flash_success( _('Thank you for contacting us, please quote #{0} in future correspondence' .format(newid))) h.redirect_to(str(data.get('referer', '/'))) except ValidationError, e: extra_vars["errors"] = e.error_dict extra_vars["error_summary"] = e.error_summary extra_vars["data"] = data c.category_id = data.get('category', '')
def delete(self, id): """Provide a delete ('withdraw') action, but only for UKLP datasets""" from ckan.lib.search import SearchIndexError context = { 'model': model, 'session': model.Session, 'user': c.user, } try: pkg_dict = get_action('package_show')(context, {'id':id}) # has side-effect of populating context.get('package') except NotAuthorized: abort(401, 'Not authorized to delete package') except ObjectNotFound: abort(404, 'Dataset not found') if request.params: # POST if 'cancel' in request.params: h.redirect_to(controller='package', action='read', id=id) elif 'delete' in request.params: try: package_name = pkg_dict['name'] get_action('package_delete')(context, {'id':id}) is_uklp = get_from_flat_dict(pkg_dict['extras'], 'UKLP') == 'True' if is_uklp: action = 'withdrawn' resource_type = get_from_flat_dict(pkg_dict['extras'], 'resource-type') + ' record' else: action = 'deleted' resource_type = 'dataset' h.flash_success('Successfully %s %s.' \ % (action, resource_type)) self._form_save_redirect(package_name, 'edit') except NotAuthorized: abort(401, _('Unauthorized to delete package %s') % id) except ObjectNotFound, e: abort(404, _('Package not found')) except DataError: abort(400, _(u'Integrity Error')) except SearchIndexError, e: abort(500, _(u'Unable to update search index.') + repr(e.args))
def commitments(self, id): """ Shows all of the commitments for the specified publisher """ from ckanext.dgu.model.commitment import Commitment context = {'model': model, 'session': model.Session, 'user': c.user or c.author, 'extras_as_string': True, 'save': 'save' in request.params} try: c.publisher_dict = get_action('organization_show')(context, {'id': id}) except NotAuthorized: abort(401, _('Unauthorized to read commitments')) except ObjectNotFound: abort(404, _('Publisher not found')) c.publisher = context.get('group') c.commitments = Commitment.get_for_publisher(c.publisher.name).order_by('commitment.dataset_name').all() return render('commitment/read.html')
def edit(self, id): """ Allows editing of commitments for a specific publisher """ from ckanext.dgu.model.commitment import Commitment from ckanext.dgu.lib import helpers as dgu_helpers context = {'model': model, 'session': model.Session, 'user': c.user or c.author, 'extras_as_string': True, 'save': 'save' in request.params} if not dgu_helpers.is_sysadmin(): abort(401, "You are not allowed to edit the commitments for this publisher") try: c.publisher_dict = get_action('organization_show')(context, {'id': id}) except NotAuthorized: abort(401, _('Unauthorized to read commitments')) except ObjectNotFound: abort(404, _('Publisher not found')) c.publisher = context.get('group') c.publishers = model.Session.query(model.Group).filter(model.Group.state=='active')\ .order_by(model.Group.title).all() c.errors = {} if request.method == "POST": # need to flatten the request into some commitments, if there is an ID then # we should update them, if there isn't then add them. # TODO: Work out how to remove them. Perhaps get the current IDs and do a diff # If successful redirect to read() h.redirect_to(h.url_for(controller='ckanext.dgu.controllers.commitment:CommitmentController', action='commitments', id=c.publisher.name)) c.commitments = Commitment.get_for_publisher(c.publisher.name).order_by('commitment.commitment_text') return render('commitment/edit.html')
def _get_package(self, id): """ Given an ID use the logic layer to fetch the Package and a dict representation of it as well as adding formatted notes and the publisher to the template context (c). """ import genshi context = {'model': model, 'session': model.Session, 'user': c.user or c.author, 'extras_as_string': True, 'for_view': True} try: c.pkg_dict = get_action('package_show')(context, {'id': id}) c.pkg = context['package'] except ObjectNotFound: abort(404, _('Dataset not found')) except NotAuthorized: abort(401, _('Unauthorized to read package %s') % id) groups = c.pkg.get_groups('organization') if groups: c.publisher = groups[0] else: log.warning("Package {0} is not a member of any group!".format(id)) # Try and render the notes as markdown for display on the page. Most # unpublished items *won't* be markdown if they've come directly from the # CSV - unless they've been edited. try: notes_formatted = render_markdown(c.pkg.notes) c.pkg_notes_formatted = unicode(genshi.HTML(notes_formatted)) c.release_notes_formatted = None notes = unpublished_release_notes(c.pkg_dict) if notes and notes.strip(): c.release_notes_formatted = unicode(genshi.HTML( render_markdown(notes))) except Exception: c.pkg_notes_formatted = c.pkg.notes
def read(self, id): from ckan.lib.search import SearchError import genshi group_type = self._get_group_type(id.split('@')[0]) context = {'model': model, 'session': model.Session, 'user': c.user or c.author, 'schema': self._form_to_db_schema(group_type=type)} data_dict = {'id': id} q = c.q = request.params.get('q', '') # unicode format (decoded from utf8) fq = '' c.is_sysadmin = Authorizer().is_sysadmin(c.user) # TODO: Deduplicate this code copied from index() # TODO: Fix this up, we only really need to do this when we are # showing the hierarchy (and then we should load on demand really). c.all_groups = model.Session.query(model.Group).\ filter(model.Group.type == 'publisher').\ filter(model.Group.state == 'active').\ order_by('title') try: c.group_dict = get_action('group_show')(context, data_dict) c.group = context['group'] except ObjectNotFound: abort(404, _('Group not found')) except NotAuthorized: abort(401, _('Unauthorized to read group %s') % id) # Search within group fq += ' parent_publishers: "%s"' % c.group_dict.get('name') description = c.group_dict.get('description','').replace('&', '&') try: description_formatted = ckan.misc.MarkdownFormat().to_html(description) c.description_formatted = genshi.HTML(description_formatted) except Exception, e: error_msg = "<span class='inline-warning'>%s</span>" % _("Cannot render description") c.description_formatted = genshi.HTML(error_msg)
def contact(self, name=None): """ This action allows users to create an issue by filling in a contact form. """ import ckan.model as model from ckanext.redmine.client import RedmineClient print name extra_vars = { "data": {}, "errors": {} } client = RedmineClient(name) c.categories = client.load_categories() c.name = name if request.method == 'POST': data = clean_dict(unflatten(tuplize_dict(parse_params(request.POST)))) context = {'model': model, 'session': model.Session, 'user': c.user} # Create the issue with the data we were passed. try: newid = get_action('issue_create')(context, data) if newid is None: self._save_on_fail(data) h.flash_success(_('Thank you for contacting us'.format(newid))) else: h.flash_success(_('Thank you for contacting us, please quote #{0} in future correspondence'.format(newid))) h.redirect_to(str(data.get('referer', '/'))) except ValidationError, e: extra_vars["errors"] = e.error_dict extra_vars["error_summary"] = e.error_summary extra_vars["data"] = data c.category_id = data.get('category','')
def delete(self, id): """Provide a delete ('withdraw') action, but only for UKLP datasets""" from ckan.lib.search import SearchIndexError context = {"model": model, "session": model.Session, "user": c.user} try: pkg_dict = get_action("package_show")( context, {"id": id} ) # has side-effect of populating context.get('package') except NotAuthorized: abort(401, "Not authorized to delete package") if request.params: # POST if "cancel" in request.params: h.redirect_to(controller="package", action="read", id=id) elif "delete" in request.params: try: package_name = pkg_dict["name"] get_action("package_delete")(context, {"id": id}) is_uklp = get_from_flat_dict(pkg_dict["extras"], "UKLP") == "True" if is_uklp: action = "withdrawn" resource_type = get_from_flat_dict(pkg_dict["extras"], "resource-type") + " record" else: action = "deleted" resource_type = "dataset" h.flash_success("Successfully %s %s." % (action, resource_type)) self._form_save_redirect(package_name, "edit") except NotAuthorized: abort(401, _("Unauthorized to delete package %s") % id) except ObjectNotFound, e: abort(404, _("Package not found")) except DataError: abort(400, _(u"Integrity Error")) except SearchIndexError, e: abort(500, _(u"Unable to update search index.") + repr(e.args))
def _save_edit(self, name_or_id, context): try: data_dict = clean_dict(unflatten( tuplize_dict(parse_params(request.POST)))) context['message'] = data_dict.get('log_message', '') data_dict['id'] = name_or_id pkg = get_action('package_update')(context, data_dict) c.pkg = context['package'] c.pkg_dict = pkg h.redirect_to(controller='package', action='read', id=pkg['name']) except NotAuthorized: abort(401, 'Not authorized to save package') except ObjectNotFound, e: abort(404, _('Dataset not found'))
def report_groups_without_admins(self): context = {'model': model, 'session': model.Session, 'user': c.user or c.author} try: check_access('group_create', context) except NotAuthorized: abort(401, _('Not authorized to see this page')) g_query = """SELECT g.* FROM public.group g WHERE id NOT IN (SELECT group_id FROM public.member WHERE capacity='admin') ORDER BY g.name;""" c.non_admin = model.Session.query(model.Group).from_statement(g_query).all() c.non_admin_count = len(c.non_admin) return render('publisher/report_groups_without_admins.html')
def report_users_not_assigned_to_groups(self): context = {'model': model, 'session': model.Session, 'user': c.user or c.author} try: check_access('group_create', context) except NotAuthorized: abort(401, _('Not authorized to see this page')) query = """SELECT * FROM public.user WHERE id NOT IN (SELECT table_id FROM public.member WHERE table_name='user') ORDER BY created desc;""" c.unassigned_users = model.Session.query(model.User).from_statement(query).all() c.unassigned_users_count = len(c.unassigned_users) return render('publisher/report_users_not_assigned_to_groups.html')
def _save_edit(self, name_or_id, context): try: data_dict = clean_dict( unflatten(tuplize_dict(parse_params(request.POST)))) context['message'] = data_dict.get('log_message', '') data_dict['id'] = name_or_id pkg = get_action('package_update')(context, data_dict) c.pkg = context['package'] c.pkg_dict = pkg h.redirect_to(controller='package', action='read', id=pkg['name']) except NotAuthorized: abort(401, 'Not authorized to save package') except ObjectNotFound, e: abort(404, _('Dataset not found'))
def report_users(self): context = {'model': model, 'session': model.Session, 'user': c.user or c.author} try: check_access('group_create', context) except NotAuthorized: abort(401, _('Not authorized to see this page')) q = model.Session.query(model.User).order_by(model.User.created.desc()) c.count = q.count() c.page = h.Page( collection=q, page=int(request.params.get('page', 1)), url=h.pager_url, items_per_page=report_limit, ) return render('publisher/report_users.html')
def _add_users(self, group, parameters): from ckan.logic.schema import default_group_schema from ckan.logic.action import error_summary from ckan.lib.dictization.model_save import group_member_save if not group: h.flash_error(_("There was a problem with your submission, \ please correct it and try again")) errors = {"reason": ["No reason was supplied"]} return self.apply(group.id, errors=errors, error_summary=error_summary(errors)) data_dict = clean_dict(unflatten( tuplize_dict(parse_params(request.params)))) data_dict['id'] = group.id # Temporary fix for strange caching during dev l = data_dict['users'] for d in l: # Form javascript creates d['capacity'] == 'undefined' for # newly added users. # If javascript in users form is not working (such as in tests) # it will not create a capacity value. if 'capacity' not in d or d['capacity'] == 'undefined': # default to 'editor' d['capacity'] = 'editor' context = { "group" : group, "schema": default_group_schema(), "model": model, "session": model.Session } # Temporary cleanup of a capacity being sent without a name users = [d for d in data_dict['users'] if len(d) == 2] data_dict['users'] = users model.repo.new_revision() group_member_save(context, data_dict, 'users') model.Session.commit() h.redirect_to('/publisher/%s' % str(group.name))
def publisher_files(self, rel_path): if not has_user_got_publisher_permissions(): abort( 401, _('You need to be logged in as an editor or admin for a' ' publisher to see these files')) path = self._get_path_relative_to_publisher_files_dir(rel_path) if not os.path.exists(path): abort(404, 'File not found') # resolve symbolic link, so it downloads with the actual filename, not # the link name if os.path.islink(path): path = os.path.realpath(path) if os.path.isdir(path): root, dirs, files = os.walk(path).next() rel_path_with_trailing_slash = rel_path.strip('/') + '/' dirs = [ dict( name=dir_, rel_path=rel_path_with_trailing_slash + dir_, ) for dir_ in dirs ] if rel_path not in ('/', '', None): dirs.insert( 0, dict(name='..', rel_path=os.path.dirname(rel_path.rstrip('/')))) file_details = [ dict( name=file, rel_path=rel_path_with_trailing_slash + file, size=os.path.getsize(root + '/' + file), modified=time.ctime(os.path.getmtime(root + '/' + file)), ) for file in files ] extra_vars = dict(dirs=dirs, file_details=file_details) return render('data/publisher_files.html', extra_vars=extra_vars) elif os.path.isfile(path): return self._serve_file(path) elif os.path.islink(path): abort(401, 'Cannot use links') else: abort(401, 'Unknown path %s' % path)
class InventoryController(BaseController): def _save_edit(self, name_or_id, context): from ckan.lib.search import SearchIndexError try: data_dict = clean_dict(unflatten( tuplize_dict(parse_params(request.POST)))) context['message'] = data_dict.get('log_message', '') data_dict['id'] = name_or_id pkg = get_action('package_update')(context, data_dict) c.pkg = context['package'] c.pkg_dict = pkg h.redirect_to(controller='package', action='read', id=pkg['name']) except NotAuthorized: abort(401, 'Not authorized to save package') except ObjectNotFound, e: abort(404, _('Dataset not found')) except DataError: abort(400, _(u'Integrity Error'))
class PackageController(ckan.controllers.package.PackageController): def history(self, id): """ Auth is different for DGU than for publisher default """ # TODO Replace user names with department names return super(PackageController, self).history(id) def delete(self, id): """Provide a delete action, but only for UKLP datasets""" from ckan.lib.search import SearchIndexError context = { 'model': model, 'session': model.Session, 'user': c.user, } pkg_dict = get_action('package_show')(context, { 'id': id }) # has side-effect of populating context.get('package') if request.params: # POST if 'cancel' in request.params: h.redirect_to(controller='package', action='read', id=id) elif 'delete' in request.params: try: package_name = pkg_dict['name'] get_action('package_delete')(context, {'id': id}) h.flash_success(_('Successfully deleted package.')) self._form_save_redirect(package_name, 'edit') except NotAuthorized: abort(401, _('Unauthorized to delete package %s') % id) except ObjectNotFound, e: abort(404, _('Package not found')) except DataError: abort(400, _(u'Integrity Error')) except SearchIndexError, e: abort(500, _(u'Unable to update search index.') + repr(e.args)) except ValidationError, e: abort(400, _('Unable to delete package.') + repr(e.error_dict))
def publisher_files(self, rel_path): if not has_user_got_publisher_permissions(): abort(401, _('You need to be logged in as an editor or admin for a' ' publisher to see these files')) path = self._get_path_relative_to_publisher_files_dir(rel_path) if not os.path.exists(path): abort(404, 'File not found') # resolve symbolic link, so it downloads with the actual filename, not # the link name if os.path.islink(path): path = os.path.realpath(path) if os.path.isdir(path): root, dirs, files = os.walk(path).next() rel_path_with_trailing_slash = rel_path.strip('/') + '/' dirs = [ dict(name=dir_, rel_path=rel_path_with_trailing_slash + dir_, ) for dir_ in dirs] if rel_path not in ('/', '', None): dirs.insert(0, dict( name='..', rel_path=os.path.dirname(rel_path.rstrip('/')))) file_details = [ dict(name=file, rel_path=rel_path_with_trailing_slash + file, size=os.path.getsize(root + '/' + file), modified=time.ctime(os.path.getmtime(root + '/' + file)), ) for file in files] extra_vars = dict(dirs=dirs, file_details=file_details) return render('data/publisher_files.html', extra_vars=extra_vars) elif os.path.isfile(path): return self._serve_file(path) elif os.path.islink(path): abort(401, 'Cannot use links') else: abort(401, 'Unknown path %s' % path)
abort(400, _(u'Integrity Error')) except SearchIndexError, e: abort(500, _(u'Unable to update search index.') + repr(e.args)) except ValidationError, e: abort(400, _('Unable to delete package.') + repr(e.error_dict)) else: abort(400, 'Parameter error') # GET c.pkg = context.get('package') try: check_access('package_delete', context) except NotAuthorized, e: abort(401, _('Unauthorized to delete package.')) package_type = self._get_package_type(id) self._setup_template_variables(context, {'id': id}, package_type=package_type) return render('package/delete.html') class CommentProxy(BaseController): '''A proxy to Drupal on another server to provide comment HTML. Useful only for test purposes, when Drupal is not present locally. ''' def get_comments(self, id): url = 'http://co-prod3.dh.bytemark.co.uk/comment/get/3266d22c-9d0f-4ebe-b0bc-ea622f858e15?comments_per_page=999999' #url = 'http://co-dev1.dh.bytemark.co.uk/comment/get/%s' % quote(id) return self._read_url(url)
abort(404, _('Package not found')) except DataError: abort(400, _(u'Integrity Error')) except SearchIndexError, e: abort(500, _(u'Unable to update search index.') + repr(e.args)) except ValidationError, e: abort(400, _('Unable to delete package.') + repr(e.error_dict)) else: abort(400, 'Parameter error') # GET c.pkg = context.get('package') try: check_access('package_delete', context) except NotAuthorized, e: abort(401, _('Unauthorized to delete package.')) package_type = self._get_package_type(id) self._setup_template_variables(context, {'id': id}, package_type=package_type) return render('package/delete.html') class CommentProxy(BaseController): '''A proxy to Drupal on another server to provide comment HTML. Useful only for test purposes, when Drupal is not present locally. ''' def get_comments(self, id): url = 'http://co-prod3.dh.bytemark.co.uk/comment/get/3266d22c-9d0f-4ebe-b0bc-ea622f858e15?comments_per_page=999999' #url = 'http://co-dev1.dh.bytemark.co.uk/comment/get/%s' % quote(id) return self._read_url(url) def _read_url(self, url, post_data=None, content_type=None): headers = {'Content-Type': content_type} if content_type else {}
pkg = get_action('package_update')(context, data_dict) c.pkg = context['package'] c.pkg_dict = pkg h.redirect_to(controller='package', action='read', id=pkg['name']) except NotAuthorized: abort(401, 'Not authorized to save package') except ObjectNotFound, e: abort(404, _('Dataset not found')) except DataError: abort(400, _(u'Integrity Error')) except SearchIndexError, e: try: exc_str = unicode(repr(e.args)) except: exc_str = unicode(str(e)) abort(500, _(u'Unable to update search index.') + exc_str) except ValidationError, e: errors = e.error_dict error_summary = e.error_summary return self.edit_item(name_or_id, data_dict, errors, error_summary) def edit_item(self, id, data=None, errors=None, error_summary=None): """ Allows for the editing of a single item """ context = {'model': model, 'session': model.Session, 'user': c.user or c.author, 'extras_as_string': True, 'save': 'save' in request.params} if context['save'] and not data: return self._save_edit(id, context)
class PackageController(ckan.controllers.package.PackageController): def __before__(self, action, **params): super(PackageController, self).__before__(action, **params) c.all_resources = 'all' in request.params.keys() def history(self, id): if not c.user: abort(401, 'Log-in to see this page') return super(PackageController, self).history(id) def all_packages(self): ctx = {'model': model, 'session': model.Session} package_list = get_action("package_list")(ctx, {}) def linkify_packages(pkgs): x = 0 for pkg in pkgs: yield '<a href="/dataset/{p}">{p}</a><br/>'.format(p=pkg) c.datasets = linkify_packages(package_list) return render("package/all_datasets.html") def delete(self, id): """Provide a delete ('withdraw') action, but only for UKLP datasets""" from ckan.lib.search import SearchIndexError context = { 'model': model, 'session': model.Session, 'user': c.user, } try: pkg_dict = get_action('package_show')(context, { 'id': id }) # has side-effect of populating context.get('package') except NotAuthorized: abort(401, 'Not authorized to delete package') if request.params: # POST if 'cancel' in request.params: h.redirect_to(controller='package', action='read', id=id) elif 'delete' in request.params: try: package_name = pkg_dict['name'] get_action('package_delete')(context, {'id': id}) is_uklp = get_from_flat_dict(pkg_dict['extras'], 'UKLP') == 'True' if is_uklp: action = 'withdrawn' resource_type = get_from_flat_dict( pkg_dict['extras'], 'resource-type') + ' record' else: action = 'deleted' resource_type = 'dataset' h.flash_success('Successfully %s %s.' \ % (action, resource_type)) self._form_save_redirect(package_name, 'edit') except NotAuthorized: abort(401, _('Unauthorized to delete package %s') % id) except ObjectNotFound, e: abort(404, _('Package not found')) except DataError: abort(400, _(u'Integrity Error')) except SearchIndexError, e: abort(500, _(u'Unable to update search index.') + repr(e.args)) except ValidationError, e: abort(400, _('Unable to delete package.') + repr(e.error_dict))
class CommitmentController(BaseController): def index(self): from ckanext.dgu.model.commitment import Commitment, ODS_ORGS c.publishers = model.Session.query(model.Group)\ .filter(model.Group.state=='active')\ .filter(model.Group.name.in_(ODS_ORGS.values()))\ .order_by(model.Group.title).all() c.commitments = model.Session.query(Commitment).filter( Commitment.state == 'active').all() return render('commitment/index.html') def commitments(self, id): """ Shows all of the commitments for the specified publisher """ from ckanext.dgu.model.commitment import Commitment context = { 'model': model, 'session': model.Session, 'user': c.user or c.author, 'extras_as_string': True, 'save': 'save' in request.params } try: c.publisher_dict = get_action('organization_show')(context, { 'id': id }) except NotAuthorized: abort(401, _('Unauthorized to read commitments')) except ObjectNotFound: abort(404, _('Publisher not found')) c.publisher = context.get('group') c.commitments = Commitment.get_for_publisher(c.publisher.name)\ .order_by('commitment.dataset_name').all() return render('commitment/read.html') def _save(self, context, data_dict, publisher): import ckan.model as model import ckanext.dgu.model.commitment as cmodel for _, items in data_dict.iteritems(): # items is now a list of dicts that can all be processed # individually if they have an ID, then we're updating, # if they don't they're new. for item in items: commitment = None if not item.get('commitment_text') and not item.get( 'dataset_name', ''): # TODO: We're ignoring empty dicts here as unfilled items but we # might well want to do some error checking too continue if item.get('id'): # Get the current commitment commitment = cmodel.Commitment.get(item.get('id')) commitment.source = item.get('source') else: commitment = cmodel.Commitment(source=item.get('source')) # text, notes, dataset (or url) commitment.commitment_text = item.get('commitment_text', '') commitment.notes = item.get('notes', '') commitment.dataset = item.get('dataset') or item.get('url') commitment.dataset_name = item.get('dataset_name', '') commitment.publisher = publisher.name commitment.author = c.user commitment.state = 'active' model.Session.add(commitment) # Commit each source to the database model.Session.commit() log.info("Commitments for {0} updated by {1}".format( publisher.name, c.user)) def edit(self, id): """ Allows editing of commitments for a specific publisher """ from ckanext.dgu.model.commitment import Commitment context = { 'model': model, 'session': model.Session, 'user': c.user, 'extras_as_string': True, 'save': 'save' in request.params } try: check_access('organization_update', {'id': id}) except Exception, e: abort(401, "Not authorised") try: c.publisher_dict = get_action('organization_show')(context, { 'id': id }) except NotAuthorized: abort(401, _('Unauthorised to read commitments')) except ObjectNotFound: abort(404, _('Publisher not found')) c.publisher = context.get('group') c.errors = {} if request.method == "POST": from ckan.logic import clean_dict, tuplize_dict, parse_params from ckan.lib.navl.dictization_functions import unflatten data_dict = clean_dict( unflatten(tuplize_dict(parse_params(request.params)))) self._save(context, data_dict, c.publisher) # We'll prefetch the available datasets for this publisher and add them to the drop-down # on the page so that we don't have to work out how to constrain an autocomplete. c.packages = model.Session.query(model.Package.name, model.Package.title)\ .filter(model.Package.state == 'active')\ .filter(model.Package.owner_org == c.publisher.id )\ .order_by(model.Package.title).all() if request.method == "POST": # need to flatten the request into some commitments, if there is an ID then # we should update them, if there isn't then add them. # TODO: Work out how to remove them. Perhaps get the current IDs and do a diff # If successful redirect to read() h.redirect_to( h.url_for( controller= 'ckanext.dgu.controllers.commitment:CommitmentController', action='commitments', id=c.publisher.name)) c.commitments = Commitment.get_for_publisher( c.publisher.name).order_by('commitment.commitment_text') return render('commitment/edit.html')
abort(404, _("Package not found")) except DataError: abort(400, _(u"Integrity Error")) except SearchIndexError, e: abort(500, _(u"Unable to update search index.") + repr(e.args)) except ValidationError, e: abort(400, _("Unable to delete package.") + repr(e.error_dict)) else: abort(400, "Parameter error") # GET c.pkg = context.get("package") try: check_access("package_delete", context) except NotAuthorized, e: abort(401, _("Unauthorized to delete package.")) package_type = self._get_package_type(id) self._setup_template_variables(context, {"id": id}, package_type=package_type) return render("package/delete.html") class CommentProxy(BaseController): """A proxy to Drupal on another server to provide comment HTML. Useful only for test purposes, when Drupal is not present locally. """ def get_comments(self, id): url = "http://uat2.lampdevelopment.co.uk/comment/get/1c65c66a-fdec-4138-9c64-0f9bf087bcbb" # url = 'http://co-dev1.dh.bytemark.co.uk/comment/get/%s' % quote(id) return self._read_url(url)