def apply(self, id=None, data=None, errors=None, error_summary=None):
        """
        Form for a user to request to be an editor for a organisation.
        It sends an email to a suitable admin.
        """
        if not c.user:
            abort(401, _('You must be logged in to apply for membership'))

        if 'parent' in request.params and not id:
            id = request.params['parent']

        if id:
            c.group = model.Group.get(id)
            if not c.group:
                log.warning('Could not find organisation for name %s', id)
                abort(404, _('Publisher not found'))
            if 'save' in request.params and not errors:
                from ckanext.dgu_orgs.model.organisation_request import OrganisationRequest

                reason = request.params.get('reason', None)

                if model.Session.query(OrganisationRequest).filter_by(
                        user_name=c.user, group_name=id).all():
                    h.flash_error(
                        'A request for this organisation is already in the system. If you have waited more than a couple of days then <a href="http://data.gov.uk/contact">contact the data.gov.uk team</a>',
                        allow_html=True)
                    h.redirect_to('organisation_apply', id=id)
                    return
                else:
                    req = OrganisationRequest(user_name=c.user,
                                              group_name=id,
                                              reason=reason)
                    model.Session.add(req)
                    model.Session.commit()

                    return self._send_application(c.group, reason)
        else:
            c.possible_parents = model.Session.query(model.Group)\
                .filter(model.Group.state=='active').order_by(model.Group.title).all()

        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('organisation/apply_form.html', extra_vars=vars)
        return render('organisation/apply.html')
    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'))

        # This used to be just used by the hierarchy but now is not, but it is
        # now used for search autocomplete and count.
        # c.all_groups = model.Session.query(model.Group).\
        #                filter(model.Group.type == 'organization').\
        #                filter(model.Group.state == 'active').\
        #                order_by('title')
        # c.page = AlphaPage(
        #     controller_name="ckanext.dgu_orgs.controllers.organisation:OrganisationController",
        #     collection=c.all_groups,
        #     page=request.params.get('page', 'A'),
        #     alpha_attribute='title',
        #     other_text=_('Other'),
        # )

        return render('organisation/index.html')
    def users(self, id, data=None, errors=None, error_summary=None):
        c.group = model.Group.by_name(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 read(self, id, limit=20):
        from ckan.lib.search import SearchError
        try:
            group_type = self._ensure_controller_matches_group_type(
                id.split('@')[0])
        except Exception:
            group_type = self._guess_group_type()
        context = {
            'model': model,
            'session': model.Session,
            'user': c.user or c.author,
            'schema': self._form_to_db_schema(
                group_type=group_type
            ),  #TODO ASH, maybe this should be _db_to_form_schema()
            'for_view': True
        }
        data_dict = {'id': id, 'type': group_type}

        try:
            # Do not query for the group datasets when dictizing, as they will
            # be ignored and get requested on the controller anyway
            context['include_datasets'] = False
            c.group_dict = get_action('organization_show')(context, data_dict)
            c.group = context['group']
        except ObjectNotFound:
            self._redirect_if_previous_name(id)
            abort(404, _('Group not found'))
        except NotAuthorized:
            abort(401, _('Unauthorized to read group %s') % id)

        c.description = c.group_dict.get('description',
                                         '').replace('&amp;', '&')
        context['return_query'] = True

        limit = 12
        try:
            page = int(request.params.get('page', 1))
        except ValueError, e:
            abort(400, ('"page" parameter must be an integer'))
    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('organisation/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('organisation/report_users_not_assigned_to_groups.html')
    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('organisation/report_users.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))

        recipients, recipient_organisation = find_group_admins(group)

        if not recipients:
            if not config.get('dgu.admin.email'):
                log.error(
                    'User "%s" prevented from applying for organisation 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": ["data.gov.uk error"]}
                return self.apply(group.id,
                                  errors=errors,
                                  error_summary=error_summary(errors))
            recipients = [(config.get('dgu.admin.name',
                                      "DGU Admin"), config['dgu.admin.email'])]
            recipient_organisation = 'data.gov.uk admin team'

        url = urljoin(
            g.site_url,
            h.url_for(
                controller=
                'ckanext.dgu_orgs.controllers.organisation:OrganisationController',
                action='users',
                id=group.name))

        log.debug(
            'User "%s" requested organisation access for "%s" which was sent to admin %s (%r) with reason: %r',
            c.user, group.name, recipient_organisation, recipients, reason)
        extra_vars = {
            'group': group,
            'requester': c.userobj,
            'reason': reason,
            'accept_url': url
        }
        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,
                    subject=
                    'DGUKOrganisationRequest: Please add me as a data.gov.uk organisation',
                    body=email_msg)
        except Exception, e:
            h.flash_error(
                'There is a problem with the system configuration. Please instead <a href="http://data.gov.uk/contact">contact the data.gov.uk team</a>',
                allow_html=True)
            errors = {"reason": ["data.gov.uk error"]}
            log.error(
                'User "%s" prevented from applying for organisation 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 _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.users(group.name,
                              errors=errors,
                              error_summary=error_summary(errors))

        data_dict = clean_dict(
            unflatten(tuplize_dict(parse_params(request.params))))
        data_dict['id'] = group.id

        # Check that the user being added, if they are a Drupal user, has
        # verified their email address
        new_users = [user['name'] for user in data_dict['users'] \
                     if not 'capacity' in user or user['capacity'] == 'undefined']

        # Removed Drupal auth stuff.
        # for user_name in new_users:
        # drupal_id = DrupalUserMapping.ckan_user_name_to_drupal_id(user_name)
        # if drupal_id:
        #     if not is_drupal_auth_activated():
        #         # joint auth with Drupal is not activated, so cannot
        #         # check with Drupal
        #         log.warning('Drupal user made editor/admin but without checking email is verified.')
        #         break
        #     if 'drupal_client' not in dir(self):
        #         self.drupal_client = DrupalClient()
        #     user_properties = self.drupal_client.get_user_properties(drupal_id)
        #     roles = user_properties['roles'].values()
        #     if 'unverified user' in roles:
        #         user = model.User.by_name(user_name)
        #         h.flash_error("There was a problem with your submission - see the error message below.")
        #         errors = {"reason": ['User "%s" has not verified their email address yet. '
        #                              'Please ask them to do this and then try again. ' % \
        #                               user.fullname]}
        #         log.warning('Trying to add user (%r %s) who is not verified to group %s',
        #                     user.fullname, user_name, group.name)
        #         # NB Other values in the form are lost, but that is probably ok
        #         return self.users(group.name, errors=errors,
        #                           error_summary=error_summary(errors))

        # 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('/organisation/%s' % str(group.name))