Beispiel #1
0
    def package_purge(self, context, data_dict):
        if not authz.Authorizer().is_sysadmin(unicode(context['user'])):
            raise NotAuthorized
        if 'id' not in data_dict:
            raise NotFound
        package = context['model'].Package.get(data_dict['id'])
        package.purge()
        package = context['model'].Session.flush()
        result = self.engine.execute(
            select(
                [self.package_table.c.nid],
                or_(self.package_table.c.id == data_dict['id'],
                    self.package_table.c.name == data_dict['id']))).fetchone()
        if not result:
            raise NotFound

        nid = result['nid']
        url = urlparse.urljoin(self.base_url,
                               'services/package/%s.json' % (nid))
        req = urllib2.Request(url)
        req.get_method = lambda: 'DELETE'
        f = urllib2.urlopen(req, None, 3)
        try:
            drupal_info = f.read()
        finally:
            f.close()

        package = context['model'].Session.commit()
Beispiel #2
0
    def setup_template_variables(self, context, data_dict):
        from pylons import config

        authz_fn = logic.get_action('group_list_authz')
        c.groups_authz = authz_fn(context, data_dict)
        data_dict.update({'available_only': True})

        c.groups_available = authz_fn(context, data_dict)

        c.licences = [('', '')] + base.model.Package.get_license_options()
        c.is_sysadmin = authz.Authorizer().is_sysadmin(c.user)

        if c.pkg:
            c.related_count = c.pkg.related_count

        ## This is messy as auths take domain object not data_dict
        context_pkg = context.get('package', None)
        pkg = context_pkg or c.pkg
        if pkg:
            try:
                if not context_pkg:
                    context['package'] = pkg
                logic.check_access('package_change_state', context)
                c.auth_for_change_state = True
            except logic.NotAuthorized:
                c.auth_for_change_state = False
Beispiel #3
0
 def _run(self):
     if not self.query.terms:
         return
     q = authz.Authorizer().authorized_query(username, model.Group)
     for term in self.query.terms:
         q = query.filter(model.Group.name.contains(term.lower()))
     self._db_query(q)
Beispiel #4
0
    def setup_class(self):
        model.repo.init_db()
        self.authorizer = authz.Authorizer()

        self.admin_role = model.Role.ADMIN
        self.editor_role = model.Role.EDITOR
        self.reader_role = model.Role.READER

        model.repo.new_revision()
        anna = model.Package(name=u'annakarenina')
        war = model.Package(name=u'warandpeace')
        mradmin = model.User(name=u'mradmin')
        mreditor = model.User(name=u'mreditor')
        mrreader = model.User(name=u'mrreader')
        tester = model.User(name=u'tester')
        anauthzgroup = model.AuthorizationGroup(name=u'anauthzgroup')
        for obj in [
                anna, war, mradmin, mreditor, mrreader, tester, anauthzgroup
        ]:
            model.Session.add(obj)
        model.repo.commit_and_remove()

        anna = model.Package.by_name(u'annakarenina')
        tester = model.User.by_name(u'tester')
        model.add_user_to_role(tester, self.admin_role, anna)

        self.context = unicode(model.Package.__name__)
        ra1 = model.RoleAction(
            role=self.admin_role,
            context=self.context,
            action=model.Action.EDIT,
        )
        ra2 = model.RoleAction(
            role=self.editor_role,
            context=self.context,
            action=model.Action.EDIT,
        )
        ra3 = model.RoleAction(
            role=self.reader_role,
            context=self.context,
            action=model.Action.READ,
        )
        for obj in [ra1, ra2, ra3]:
            model.Session.add(obj)
        model.repo.commit_and_remove()

        mradmin = model.User.by_name(u'mradmin')
        mreditor = model.User.by_name(u'mreditor')
        mrreader = model.User.by_name(u'mrreader')
        model.add_user_to_role(mradmin, self.admin_role, anna)
        model.add_user_to_role(mreditor, self.editor_role, anna)
        model.add_user_to_role(mrreader, self.reader_role, anna)
        model.repo.commit_and_remove()

        self.mradmin = model.User.by_name(u'mradmin')
        self.mreditor = model.User.by_name(u'mreditor')
        self.mrreader = model.User.by_name(u'mrreader')
        self.war = model.Package.by_name(u'warandpeace')
        self.anna = model.Package.by_name(u'annakarenina')
Beispiel #5
0
    def test_05_author_is_new_package_admin(self):
        user = self.mrloggedin
        
        # make new package
        assert not model.Package.by_name(u'annakarenina')
        offset = url_for(controller='package', action='new')
        res = self.app.get(offset, extra_environ={'REMOTE_USER': user.name.encode('utf8')})
        assert 'New - Data Packages' in res
        fv = res.forms['package-edit']
        prefix = ''
        fv[prefix + 'name'] = u'annakarenina'
        res = fv.submit('save', extra_environ={'REMOTE_USER': user.name.encode('utf8')})

        # check user is admin
        pkg = model.Package.by_name(u'annakarenina')
        assert pkg
        roles = authz.Authorizer().get_roles(user.name, pkg)
        assert model.Role.ADMIN in roles, roles
        roles = authz.Authorizer().get_roles(u'someoneelse', pkg)
        assert not model.Role.ADMIN in roles, roles
Beispiel #6
0
 def setup_class(self):
     model.Session.remove()
     model.repo.init_db()
     model.repo.new_revision()
     p1 = model.Package(name=u'annakarenina')
     p2 = model.Package(name=u'warandpeace')
     p3 = model.Package(name=u'test0')
     mradmin = model.User(name=u'tester')
     for obj in (p1, p2, p3, mradmin):
         model.Session.add(obj)
     self.authorizer = authz.Authorizer()
     model.repo.commit_and_remove()
Beispiel #7
0
    def setup_class(self):
        CreateTestData.create()
        model.repo.new_revision()
        self.authorizer = authz.Authorizer()
        pkg = model.Package(name=u'testpkg')
        joeadmin = model.User.by_name(u'joeadmin')
        assert joeadmin
        model.setup_default_user_roles(pkg, [joeadmin])
        model.repo.commit_and_remove()

        self.pkg = model.Package.by_name(u'testpkg')
        self.joeadmin = model.User.by_name(u'joeadmin')
        self.logged_in = model.User.by_name(model.PSEUDO_USER__LOGGED_IN)
        self.visitor = model.User.by_name(model.PSEUDO_USER__VISITOR)
Beispiel #8
0
    def setup_template_variables(self, context, data_dict):
        c.is_sysadmin = authz.Authorizer().is_sysadmin(c.user)

        ## This is messy as auths take domain object not data_dict
        context_group = context.get('group', None)
        group = context_group or c.group
        if group:
            try:
                if not context_group:
                    context['group'] = group
                logic.check_access('group_change_state', context)
                c.auth_for_change_state = True
            except logic.NotAuthorized:
                c.auth_for_change_state = False
Beispiel #9
0
 def index(self):
     
     if not self.authorizer.am_authorized(c, model.Action.SITE_READ, model.System):
         abort(401, _('Not authorized to see this page'))
     
     query = authz.Authorizer().authorized_query(c.user, model.Group)
     query = query.order_by(model.Group.name.asc())
     query = query.order_by(model.Group.title.asc())
     c.page = Page(
         collection=query,
         page=request.params.get('page', 1),
         items_per_page=20
     )
     return render('group/index.html')
Beispiel #10
0
    def setup_template_variables(self, context, data_dict):
        from pylons import config

        data_dict.update({'available_only': True})

        c.groups_available = c.userobj and \
            c.userobj.get_groups('organization') or []
        c.licences = [('', '')] + base.model.Package.get_license_options()
        c.is_sysadmin = authz.Authorizer().is_sysadmin(c.user)

        ## This is messy as auths take domain object not data_dict
        context_pkg = context.get('package', None)
        pkg = context_pkg or c.pkg
        if pkg:
            try:
                if not context_pkg:
                    context['package'] = pkg
                check_access('package_change_state', context)
                c.auth_for_change_state = True
            except NotAuthorized:
                c.auth_for_change_state = False
Beispiel #11
0
    def setup_class(self):
        model.Session.remove()
        CreateTestData.create()
        model.Session.remove()
        self.authorizer = authz.Authorizer()

        self.admin_role = model.Role.ADMIN
        self.editor_role = model.Role.EDITOR
        self.reader_role = model.Role.READER

        john = model.User(name=u'john')
        model.Session.add(john)

        # setup annakarenina with default roles
        anna = model.Package.by_name(u'annakarenina')
        model.clear_user_roles(anna)
        annakarenina_creator = model.User(name=u'annakarenina_creator')
        model.Session.add(annakarenina_creator)
        model.repo.commit_and_remove()
        model.setup_default_user_roles(anna, [annakarenina_creator])
        model.repo.commit_and_remove()

        # setup warandpeace with no roles
        war = model.Package.by_name(u'warandpeace')
        model.clear_user_roles(war)

        # setup restricted package - visitors can't change
        restricted = model.Package(name=u'restricted')
        vrestricted = model.Package(name=u'vrestricted')
        mreditor = model.User(name=u'mreditor')
        mrreader = model.User(name=u'mrreader')
        self.mrsysadmin = u'mrsysadmin'
        mrsysadmin = model.User(name=self.mrsysadmin)
        model.repo.new_revision()
        model.Session.add_all(
            [restricted, vrestricted, mreditor, mrreader, mrsysadmin])
        model.repo.commit_and_remove()
        visitor_roles = []
        logged_in_roles = [model.Role.EDITOR, model.Role.READER]
        logged_in_roles_v = []
        restricted = model.Package.by_name(u'restricted')
        vrestricted = model.Package.by_name(u'vrestricted')
        model.setup_user_roles(restricted, visitor_roles, logged_in_roles)
        model.setup_user_roles(vrestricted, visitor_roles, logged_in_roles_v)
        model.repo.commit_and_remove()
        mreditor = model.User.by_name(u'mreditor')
        model.add_user_to_role(mreditor, model.Role.EDITOR, restricted)

        mrsysadmin = model.User.by_name(u'mrsysadmin')
        model.add_user_to_role(mrsysadmin, model.Role.ADMIN, model.System())
        model.repo.commit_and_remove()

        self.mreditor = model.User.by_name(u'mreditor')
        self.mrreader = model.User.by_name(u'mrreader')
        self.annakarenina_creator = model.User.by_name(u'annakarenina_creator')
        self.logged_in = model.User.by_name(model.PSEUDO_USER__LOGGED_IN)
        self.visitor = model.User.by_name(model.PSEUDO_USER__VISITOR)
        self.john = model.User.by_name(u'john')
        self.war = model.Package.by_name(u'warandpeace')
        self.anna = model.Package.by_name(u'annakarenina')
        self.restricted = model.Package.by_name(u'restricted')
        self.vrestricted = model.Package.by_name(u'vrestricted')
Beispiel #12
0
    def migrate_data(self, context, data_dict):
        if not authz.Authorizer().is_sysadmin(unicode(context['user'])):
            raise NotAuthorized
        model.Session.remove()
        model.Session().connection
        conn_ckan = model.Session.connection()
        conn_drupal = self.engine.connect()

        #package
        packages = conn_ckan.execute(
            select([model.package_revision_table],
                   and_(
                       model.package_revision_table.c.current == True,
                       model.package_revision_table.c.state.in_(
                           ['active', 'deleted'])))).fetchall()
        package_inserts = []
        for package in packages:
            insert = {}
            for column in self.package_table.c:
                if column in package:
                    insert[column.name] = package[column.name]
            package_inserts.append(insert)
        conn_drupal.execute(self.package_table.insert(), package_inserts)
        print 'packages done'

        #resources
        resources = conn_ckan.execute(
            select([
                model.resource_revision_table,
                model.resource_group_table.c.package_id
            ],
                   and_(
                       model.resource_revision_table.c.current == True,
                       model.resource_revision_table.c.state.in_(
                           ['active', 'deleted']),
                       model.resource_group_table.c.id ==
                       model.resource_revision_table.c.resource_group_id,
                   ))).fetchall()

        resource_inserts = []
        for resource in resources:
            insert = {}
            for column in self.resource_table.c:
                if column in resource:
                    insert[column.name] = resource[column.name]
            insert['extras'] = json.dumps(insert['extras'])
            resource_inserts.append(insert)
        conn_drupal.execute(self.resource_table.insert(), resource_inserts)
        print 'resources done'

        #extras
        extras = conn_ckan.execute(
            select([model.extra_revision_table],
                   and_(
                       model.extra_revision_table.c.current == True,
                       model.extra_revision_table.c.state.in_(
                           ['active', 'deleted'])))).fetchall()
        package_extra_inserts = []
        for extra in extras:
            insert = {}
            for column in self.package_extra_table.c:
                if column in extra:
                    insert[column.name] = extra[column.name]
            insert['value'] = json.dumps(insert['value'])
            package_extra_inserts.append(insert)
        conn_drupal.execute(self.package_extra_table.insert(),
                            package_extra_inserts)
        print 'extras done'

        #tags
        tags = conn_ckan.execute(
            select([model.package_tag_revision_table, model.tag_table.c.name],
                   and_(
                       model.package_tag_revision_table.c.current == True,
                       model.package_tag_revision_table.c.state.in_(
                           ['active', 'deleted']), model.tag_table.c.id ==
                       model.package_tag_revision_table.c.tag_id))).fetchall()
        tag_inserts = []
        for tag in tags:
            tag_inserts.append({
                'name': tag['name'],
                'id': tag['id'],
                'package_id': tag['package_id']
            })
        conn_drupal.execute(self.tag_table.insert(), tag_inserts)
        print 'tags done'

        ## get nodes

        packages = conn_drupal.execute(select(
            [self.package_table], )).fetchall()

        for num, package in enumerate(packages):
            print num
            data_dict = {}
            for column in self.package_table.c:
                data_dict[column.name] = package[column.name]
            url = urlparse.urljoin(self.base_url, 'services/package.json')
            data_dict['body'] = data_dict.get('notes', '')
            if not data_dict['title']:
                data_dict['title'] = data_dict['name']
            tags = conn_drupal.execute(
                select(
                    [self.tag_table.c.name],
                    self.tag_table.c.package_id == package['id'])).fetchall()
            data_dict['tags'] = [{'name': tag[0]} for tag in tags]
            data = json.dumps({'data': data_dict})
            req = urllib2.Request(url, data,
                                  {'Content-type': 'application/json'})
            f = urllib2.urlopen(req, None, 3)
            try:
                drupal_info = json.loads(f.read())
            finally:
                f.close()
            nid = drupal_info['nid']
            update = {'nid': nid}

            conn_drupal.execute(self.package_table.update().where(
                self.package_table.c.id == data_dict['id']).values(nid=nid))

        conn_drupal.execute(
            'update ckan_resource set nid = (select nid from ckan_package where ckan_resource.package_id = ckan_package.id);'
        )
        conn_drupal.execute(
            'update ckan_package_extra set nid = (select nid from ckan_package where ckan_package_extra.package_id = ckan_package.id);'
        )
        conn_drupal.execute(
            'update ckan_tag set nid = (select nid from ckan_package where ckan_tag.package_id = ckan_package.id);'
        )
        print 'finished migration'
Beispiel #13
0
class BaseController(WSGIController):
    repo = model.repo
    authorizer = authz.Authorizer()
    log = logging.getLogger(__name__)

    def __before__(self, action, **params):
        c.__version__ = ckan.__version__
        self._identify_user()
        i18n.handle_request(request, c)

    def _identify_user(self):
        # see if it was proxied first
        c.remote_addr = request.environ.get('HTTP_X_FORWARDED_FOR', '')
        if not c.remote_addr:
            c.remote_addr = request.environ.get('REMOTE_ADDR', 'Unknown IP Address')

        # what is different between session['user'] and environ['REMOTE_USER']
        c.user = request.environ.get('REMOTE_USER', '')
        if c.user:
            c.user = c.user.decode('utf8')
            c.userobj = model.User.by_name(c.user)
        else:
            c.userobj = self._get_user_for_apikey()
            if c.userobj is not None:
                c.user = c.userobj.name
        if c.user:
            c.author = c.user
        else:
            c.author = c.remote_addr
        c.author = unicode(c.author)

    def __call__(self, environ, start_response):
        """Invoke the Controller"""
        # WSGIController.__call__ dispatches to the Controller method
        # the request is routed to. This routing information is
        # available in environ['pylons.routes_dict']    
        try:
            return WSGIController.__call__(self, environ, start_response)
        finally:
            model.Session.remove()

    def __after__(self, action, **params):
        return

    def _get_user(self, reference):
        return model.User.by_name(reference)

    def _get_pkg(self, reference):
        return model.Package.get(reference)

    def _get_group(self, reference):
        return model.Group.get(reference)

    def _get_tag(self, reference):
        return model.Tag.get(reference)

    @classmethod
    def _get_request_data(cls):
        '''Returns a dictionary, extracted from a request. The request data is
        in POST data and formatted as a dictionary that has been
        JSON-encoded.

        If there is no data, None or "" is returned.
        ValueError will be raised if the data is not a JSON-formatted dict.
        
        '''
        cls.log.debug('Retrieving request params: %r' % request.params)
        cls.log.debug('Retrieving request POST: %r' % request.POST)
        request_data = None
        if request.POST:
            try:
                request_data = request.POST.keys()
            except Exception, inst:
                msg = _("Could not find the POST data: %r : %s") % \
                      (request.POST, inst)
                raise ValueError, msg
            request_data = request_data[0]
        else:
Beispiel #14
0
class BaseController(WSGIController):
    repo = model.repo
    authorizer = authz.Authorizer()
    log = logging.getLogger(__name__)

    def __before__(self, action, **params):
        c.__version__ = ckan.__version__
        self._identify_user()
        i18n.handle_request(request, c)

    def _identify_user(self):
        '''
        Identifies the user using two methods:
        a) If he has logged into the web interface then repoze.who will
           set REMOTE_USER.
        b) For API calls he may set a header with his API key.
        If the user is identified then:
          c.user = user name (unicode)
          c.userobj = user object
          c.author = user name
        otherwise:
          c.user = None
          c.userobj = None
          c.author = user\'s IP address (unicode)
        '''
        # see if it was proxied first
        c.remote_addr = request.environ.get('HTTP_X_FORWARDED_FOR', '')
        if not c.remote_addr:
            c.remote_addr = request.environ.get('REMOTE_ADDR',
                                                'Unknown IP Address')

        # environ['REMOTE_USER'] is set by repoze.who if it authenticates a user's
        # cookie or OpenID. But repoze.who doesn't check the user (still)
        # exists in our database - we need to do that here. (Another way would
        # be with an userid_checker, but that would mean another db access.
        # See: http://docs.repoze.org/who/1.0/narr.html#module-repoze.who.plugins.sql )
        c.user = request.environ.get('REMOTE_USER', '')
        if c.user:
            c.user = c.user.decode('utf8')
            c.userobj = model.User.by_name(c.user)
            if c.userobj is None:
                # This occurs when you are logged in, clean db
                # and then restart i.e. only really for testers. There is no
                # user object, so even though repoze thinks you are logged in
                # and your cookie has ckan_display_name, we need to force user
                # to logout and login again to get the User object.
                c.user = None
                self.log.warn('Logout to login')
        else:
            c.userobj = self._get_user_for_apikey()
            if c.userobj is not None:
                c.user = c.userobj.name
        if c.user:
            c.author = c.user
        else:
            c.author = c.remote_addr
        c.author = unicode(c.author)

    def __call__(self, environ, start_response):
        """Invoke the Controller"""
        # WSGIController.__call__ dispatches to the Controller method
        # the request is routed to. This routing information is
        # available in environ['pylons.routes_dict']

        try:
            res = WSGIController.__call__(self, environ, start_response)
        finally:
            model.Session.remove()

        # Clean out any old cookies as they may contain api keys etc
        # This also improves the cachability of our pages as cookies
        # prevent proxy servers from caching content unless they have
        # been configured to ignore them.
        for cookie in request.cookies:
            if cookie.startswith('ckan') and cookie not in ['ckan']:
                response.delete_cookie(cookie)
            # Remove the ckan session cookie if not used e.g. logged out
            elif cookie == 'ckan' and not c.user:
                # Check session for valid data (including flash messages)
                # (DGU also uses session for a shopping basket-type behaviour)
                is_valid_cookie_data = False
                for key, value in session.items():
                    if not key.startswith('_') and value:
                        is_valid_cookie_data = True
                        break
                if not is_valid_cookie_data:
                    if session.id:
                        if not session.get('lang'):
                            self.log.debug(
                                'No session data any more - deleting session')
                            self.log.debug('Session: %r', session.items())
                            session.delete()
                    else:
                        response.delete_cookie(cookie)
                        self.log.debug(
                            'No session data any more - deleting session cookie'
                        )
            # Remove auth_tkt repoze.who cookie if user not logged in.
            elif cookie == 'auth_tkt' and not session.id:
                response.delete_cookie(cookie)

        return res

    def __after__(self, action, **params):
        self._set_cors()

    def _set_cors(self):
        response.headers['Access-Control-Allow-Origin'] = "*"
        response.headers[
            'Access-Control-Allow-Methods'] = "POST, PUT, GET, DELETE, OPTIONS"
        response.headers[
            'Access-Control-Allow-Headers'] = "X-CKAN-API-KEY, Authorization, Content-Type"

    def _get_user(self, reference):
        return model.User.by_name(reference)

    def _get_pkg(self, reference):
        return model.Package.get(reference)

    def _get_group(self, reference):
        return model.Group.get(reference)

    def _get_tag(self, reference):
        return model.Tag.get(reference)

    @classmethod
    def _get_request_data(cls, try_url_params=False):
        '''Returns a dictionary, extracted from a request.

        If there is no data, None or "" is returned.
        ValueError will be raised if the data is not a JSON-formatted dict.

        The data is retrieved as a JSON-encoded dictionary from the request
        body.  Or, if the `try_url_params` argument is True and the request is
        a GET request, then an attempt is made to read the data from the url
        parameters of the request.

        try_url_params
            If try_url_params is False, then the data_dict is read from the
            request body.

            If try_url_params is True and the request is a GET request then the
            data is read from the url parameters.  The resulting dict will only
            be 1 level deep, with the url-param fields being the keys.  If a
            single key has more than one value specified, then the value will
            be a list of strings, otherwise just a string.

        This function is only used by the API, so no strings need to be
        translated.

        TODO: If this is only used by the API, then perhaps it should be
              moved to the api controller class?
        '''
        cls.log.debug('Retrieving request params: %r' % request.params)
        cls.log.debug('Retrieving request POST: %r' % request.POST)
        cls.log.debug('Retrieving request GET: %r' % request.GET)
        request_data = None
        if request.POST:
            try:
                keys = request.POST.keys()
                # Parsing breaks if there is a = in the value, so for now
                # we will check if the data is actually all in a single key
                if keys and request.POST[keys[0]] in [u'1', u'']:
                    request_data = keys[0]
                else:
                    request_data = urllib.unquote_plus(request.body)
            except Exception, inst:
                msg = "Could not find the POST data: %r : %s" % \
                      (request.POST, inst)
                raise ValueError, msg

        elif try_url_params and request.GET:
            return request.GET.mixed()
Beispiel #15
0
class BaseController(WSGIController):
    repo = model.repo
    authorizer = authz.Authorizer()
    log = logging.getLogger(__name__)

    def __before__(self, action, **params):
        c.__version__ = ckan.__version__
        self._identify_user()
        i18n.handle_request(request, c)

    def _identify_user(self):
        '''
        Identifies the user using two methods:
        a) If he has logged into the web interface then repoze.who will
           set REMOTE_USER.
        b) For API calls he may set a header with his API key.
        If the user is identified then:
          c.user = user name (unicode)
          c.author = user name
        otherwise:
          c.user = None
          c.author = user\'s IP address (unicode)
        '''
        # see if it was proxied first
        c.remote_addr = request.environ.get('HTTP_X_FORWARDED_FOR', '')
        if not c.remote_addr:
            c.remote_addr = request.environ.get('REMOTE_ADDR',
                                                'Unknown IP Address')

        # what is different between session['user'] and environ['REMOTE_USER']
        c.user = request.environ.get('REMOTE_USER', '')
        if c.user:
            c.user = c.user.decode('utf8')
            c.userobj = model.User.by_name(c.user)
            if c.userobj is None:
                # This occurs when you are logged in, clean db
                # and then restart i.e. only really for testers. There is no
                # user object, so even though repoze thinks you are logged in
                # and your cookie has ckan_display_name, we need to force user
                # to logout and login again to get the User object.
                c.user = None
        else:
            c.userobj = self._get_user_for_apikey()
            if c.userobj is not None:
                c.user = c.userobj.name
        if c.user:
            c.author = c.user
        else:
            c.author = c.remote_addr
        c.author = unicode(c.author)

    def __call__(self, environ, start_response):
        """Invoke the Controller"""
        # WSGIController.__call__ dispatches to the Controller method
        # the request is routed to. This routing information is
        # available in environ['pylons.routes_dict']

        # Clean out any old cookies as they may contain api keys etc
        # This also improves the cachability of our pages as cookies
        # prevent proxy servers from caching content unless they have
        # been configured to ignore them.
        for cookie in request.cookies:
            if cookie.startswith('ckan') and cookie not in ['ckan']:
                response.delete_cookie(cookie)
            # Remove the ckan session cookie if not used e.g. logged out
            elif cookie == 'ckan' and not c.user and not h.are_there_flash_messages(
            ):
                if session.id:
                    if not session.get('lang'):
                        session.delete()
                else:
                    response.delete_cookie(cookie)
            # Remove auth_tkt repoze.who cookie if user not logged in.
            elif cookie == 'auth_tkt' and not session.id:
                response.delete_cookie(cookie)

        try:
            return WSGIController.__call__(self, environ, start_response)
        finally:
            model.Session.remove()

    def __after__(self, action, **params):
        self._set_cors()

    def _set_cors(self):
        response.headers['Access-Control-Allow-Origin'] = "*"
        response.headers[
            'Access-Control-Allow-Methods'] = "POST, PUT, GET, DELETE"
        response.headers[
            'Access-Control-Allow-Headers'] = "X-CKAN-API-KEY, Content-Type"

    def _get_user(self, reference):
        return model.User.by_name(reference)

    def _get_pkg(self, reference):
        return model.Package.get(reference)

    def _get_group(self, reference):
        return model.Group.get(reference)

    def _get_tag(self, reference):
        return model.Tag.get(reference)

    @classmethod
    def _get_request_data(cls):
        '''Returns a dictionary, extracted from a request. The request data is
        in POST data and formatted as a dictionary that has been
        JSON-encoded.

        If there is no data, None or "" is returned.
        ValueError will be raised if the data is not a JSON-formatted dict.

        This function is only used by the API, so no strings need to be
        translated.
        '''
        cls.log.debug('Retrieving request params: %r' % request.params)
        cls.log.debug('Retrieving request POST: %r' % request.POST)
        request_data = None
        if request.POST:
            try:
                keys = request.POST.keys()
                # Parsing breaks if there is a = in the value, so for now
                # we will check if the data is actually all in a single key
                if keys and request.POST[keys[0]] in [u'1', u'']:
                    request_data = keys[0]
                else:
                    request_data = urllib.unquote_plus(request.body)
            except Exception, inst:
                msg = "Could not find the POST data: %r : %s" % \
                      (request.POST, inst)
                raise ValueError, msg
        else:
Beispiel #16
0
class BaseController(WSGIController):
    repo = model.repo
    authorizer = authz.Authorizer()
    log = logging.getLogger(__name__)

    def __before__(self, action, **params):
        c.__version__ = ckan.__version__
        self._identify_user()
        i18n.handle_request(request, c)

    def _identify_user(self):
        # see if it was proxied first
        c.remote_addr = request.environ.get('HTTP_X_FORWARDED_FOR', '')
        if not c.remote_addr:
            c.remote_addr = request.environ.get('REMOTE_ADDR', 'Unknown IP Address')

        # what is different between session['user'] and environ['REMOTE_USER']
        c.user = request.environ.get('REMOTE_USER', '')
        if c.user:
            c.user = c.user.decode('utf8')
            c.userobj = model.User.by_name(c.user)
            if c.userobj is None:
                # This occurs when you are logged in with openid, clean db
                # and then restart i.e. only really for testers. There is no
                # user object, so even though repoze thinks you are logged in
                # and your cookie has ckan_display_name, we need to force user
                # to login again to get the User object.
                c.user = None
        else:
            c.userobj = self._get_user_for_apikey()
            if c.userobj is not None:
                c.user = c.userobj.name
        if c.user:
            c.author = c.user
        else:
            c.author = c.remote_addr
        c.author = unicode(c.author)

    def __call__(self, environ, start_response):
        """Invoke the Controller"""
        # WSGIController.__call__ dispatches to the Controller method
        # the request is routed to. This routing information is
        # available in environ['pylons.routes_dict']    
        try:
            return WSGIController.__call__(self, environ, start_response)
        finally:
            model.Session.remove()

    def __after__(self, action, **params):
        self._set_cors()

    def _set_cors(self):
        response.headers['Access-Control-Allow-Origin'] = "*"
        response.headers['Access-Control-Allow-Methods'] = "POST, PUT, GET, DELETE"
        response.headers['Access-Control-Allow-Headers'] = "X-CKAN-API-KEY, Content-Type"

    def _get_user(self, reference):
        return model.User.by_name(reference)

    def _get_pkg(self, reference):
        return model.Package.get(reference)

    def _get_group(self, reference):
        return model.Group.get(reference)

    def _get_tag(self, reference):
        return model.Tag.get(reference)

    @classmethod
    def _get_request_data(cls):
        '''Returns a dictionary, extracted from a request. The request data is
        in POST data and formatted as a dictionary that has been
        JSON-encoded.

        If there is no data, None or "" is returned.
        ValueError will be raised if the data is not a JSON-formatted dict.

        This function is only used by the API, so no strings need to be
        translated.
        '''
        cls.log.debug('Retrieving request params: %r' % request.params)
        cls.log.debug('Retrieving request POST: %r' % request.POST)
        request_data = None
        if request.POST:
            try:
                request_data = request.POST.keys()
            except Exception, inst:
                msg = "Could not find the POST data: %r : %s" % \
                      (request.POST, inst)
                raise ValueError, msg
            request_data = request_data[0]
        else:
Beispiel #17
0
    def setup_template_variables(self, context, data_dict):
        data_dict.update({'available_only': True})

        toolkit.c.groups_available = toolkit.c.userobj and \
            toolkit.c.userobj.get_groups('organization') or []
        toolkit.c.licences = [('', '')
                              ] + base.model.Package.get_license_options()
        toolkit.c.is_sysadmin = authz.Authorizer().is_sysadmin(toolkit.c.user)

        ## This is messy as auths take domain object not data_dict
        context_pkg = context.get('package', None)
        pkg = context_pkg or toolkit.c.pkg
        if pkg:
            try:
                if not context_pkg:
                    context['package'] = pkg
                logic.check_access('package_change_state', context)
                toolkit.c.auth_for_change_state = True
            except logic.NotAuthorized:
                toolkit.c.auth_for_change_state = False

        #Get MetroPulse fields and add them to the form
        here = os.path.dirname(__file__)
        rootdir = os.path.dirname(os.path.dirname(here))

        if 'cmap_data_family' in toolkit.c.pkg_dict:
            data_family = toolkit.c.pkg_dict['cmap_data_family']
        else:
            data_family = ''

        if 'cmap_data_category' in toolkit.c.pkg_dict:
            data_cat = toolkit.c.pkg_dict['cmap_data_category']
        else:
            data_cat = ''

        if 'cmap_data_subcategory' in toolkit.c.pkg_dict:
            data_subcat = toolkit.c.pkg_dict['cmap_data_subcategory']
        else:
            data_subcat = ''

        geogLevelsFile = open(
            os.path.join(rootdir, 'MetroPulseGeogLevels.xml'), 'r')
        geogLevelsXml = geogLevelsFile.read()

        fieldsFile = open(os.path.join(rootdir, 'MetroPulseFields.xml'), 'r')
        fieldsXml = fieldsFile.read()

        geogLevelsList = metropulse.getFilteredChildren(
            geogLevelsXml, "geoglevels", ('id', 'name'))
        toolkit.c.cmap_geog_levels = geogLevelsList

        dataFamilyList = metropulse.getFilteredChildren(
            fieldsXml, "data", ('id', 'caption'))
        toolkit.c.cmap_data_families = dataFamilyList

        # attributeRegEx regular expression narrows future values to ones
        # that are children of current values (makes sure selections make sense together)

        attributeRegEx = {'id': data_family}
        dataCatList = metropulse.getFilteredChildren(fieldsXml, "datafamily",
                                                     ('id', 'caption'),
                                                     attributeRegEx)
        toolkit.c.cmap_data_categories = dataCatList

        attributeRegEx = {'id': data_cat}
        dataSubcatList = metropulse.getFilteredChildren(
            fieldsXml, "datacat", ('id', 'caption'), attributeRegEx)
        toolkit.c.cmap_data_subcategories = dataSubcatList

        attributeRegEx = {'id': data_subcat}
        dataFieldList = metropulse.getFilteredChildren(fieldsXml, "datasubcat",
                                                       ('id', 'caption'),
                                                       attributeRegEx)
        toolkit.c.cmap_data_fields = dataFieldList
Beispiel #18
0
    def _run(self):
        q = authz.Authorizer().authorized_query(self.options.get('username'),
                                                model.Package)
        make_like = lambda x, y: x.ilike(u'%' + unicode(y) + u'%')
        q = q.filter(
            model.package_search_table.c.package_id == model.Package.id)

        all_terms = ''
        if self.query.query != '*:*':
            # Full search by general terms (and field specific terms but not by field)
            terms_set = set(self.query.terms)
            terms_set.update(self.query.fields.values())
            all_terms = u' '.join(map(unicode, terms_set))

            if len(all_terms.strip()):
                q = q.filter(
                    u'package_search.search_vector @@ plainto_tsquery(:terms)')
                q = q.params(terms=all_terms)

            # Filter by field specific terms
            for field, terms in self.query.fields.items():
                if field == 'tags':
                    q = self._filter_by_tag(q, terms)
                    continue
                elif field == 'groups':
                    q = self._filter_by_group(q, terms)
                    continue

                if isinstance(terms, basestring):
                    terms = terms.split()

                if field in model.package_table.c:
                    model_attr = getattr(model.Package, field)
                    for term in terms:
                        q = q.filter(make_like(model_attr, term))
                else:
                    q = self._filter_by_extra(q, field, terms)

        # Filter for options
        if self.options.filter_by_downloadable:
            q = q.join('resource_groups_all', 'resources_all', aliased=True)
            q = q.filter(
                sqlalchemy.and_(
                    model.Resource.state == model.State.ACTIVE,
                    model.ResourceGroup.package_id == model.Package.id))
        if self.options.filter_by_openness:
            q = q.filter(model.Package.license_id.in_(self.open_licenses))

        order_by = self.options.order_by
        if order_by is not None:
            if order_by == 'rank':
                q = q.add_column(
                    sqlalchemy.func.ts_rank_cd(
                        sqlalchemy.text('package_search.search_vector'),
                        sqlalchemy.func.plainto_tsquery(all_terms)))
                q = q.order_by(sqlalchemy.text('ts_rank_cd_1 DESC'))
            elif hasattr(model.Package, order_by):
                q = q.order_by(getattr(model.Package, order_by))
            else:
                # TODO extras
                raise NotImplemented

        q = q.distinct()
        self._db_query(q)