Ejemplo n.º 1
0
    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')
Ejemplo n.º 2
0
    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))
Ejemplo n.º 3
0
    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))
Ejemplo n.º 4
0
    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))
Ejemplo n.º 5
0
    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')
Ejemplo n.º 6
0
    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))
Ejemplo n.º 7
0
    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')
Ejemplo n.º 8
0
    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")
Ejemplo n.º 9
0
    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))
Ejemplo n.º 10
0
    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')
Ejemplo n.º 11
0
 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
Ejemplo n.º 12
0
    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))
Ejemplo n.º 13
0
    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
Ejemplo n.º 14
0
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))
Ejemplo n.º 15
0
 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', '')
Ejemplo n.º 17
0
    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))
Ejemplo n.º 18
0
    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')
Ejemplo n.º 19
0
    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')
Ejemplo n.º 20
0
    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
Ejemplo n.º 21
0
    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)
Ejemplo n.º 22
0
    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','')
Ejemplo n.º 23
0
    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))
Ejemplo n.º 24
0
    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'))
Ejemplo n.º 25
0
    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')
Ejemplo n.º 26
0
    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')
Ejemplo n.º 27
0
    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'))
Ejemplo n.º 28
0
    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')
Ejemplo n.º 29
0
    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))
Ejemplo n.º 30
0
 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)
Ejemplo n.º 31
0
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'))
Ejemplo n.º 32
0
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))
Ejemplo n.º 33
0
 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)
Ejemplo n.º 34
0
                    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)
Ejemplo n.º 35
0
                    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 {}
Ejemplo n.º 36
0
            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)
Ejemplo n.º 37
0
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))
Ejemplo n.º 38
0
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')
Ejemplo n.º 39
0
                    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)