Skip to content

Commit

Permalink
Merge branch 'master' into clean-models
Browse files Browse the repository at this point in the history
Conflicts:
	ckan/model/__init__.py
	ckan/model/group.py
  • Loading branch information
tobes committed May 8, 2012
2 parents 7053980 + 20d06d6 commit 36ba5e6
Show file tree
Hide file tree
Showing 69 changed files with 1,232 additions and 1,502 deletions.
26 changes: 18 additions & 8 deletions ckan/authz.py
Expand Up @@ -154,13 +154,23 @@ def get_roles(cls, username, domain_obj):
return [pr.role for pr in q]

@classmethod
def is_sysadmin(cls, username):
user = model.User.by_name(username, autoflush=False)
if user:
q = model.Session.query(model.SystemRole)
q = q.autoflush(False)
q = q.filter_by(role=model.Role.ADMIN, user=user)
return q.count() > 0
def is_sysadmin(cls, user):
'''Returns whether the given user a sys-admin?
(sysadmin = system administrator with full authorization)
Ideally provide a user object. Next best is a user name.
'''
if not user:
return False
if isinstance(user, basestring):
user = model.User.by_name(user, autoflush=False)
if not user:
return False
elif not isinstance(user, model.User):
raise NotImplementedError
q = model.Session.query(model.SystemRole)
q = q.autoflush(False)
q = q.filter_by(role=model.Role.ADMIN, user=user)
return q.count() > 0

@classmethod
def get_admins(cls, domain_obj):
Expand Down Expand Up @@ -188,7 +198,7 @@ def authorized_query(cls, username, entity, action=model.Action.READ):
visitor = model.User.by_name(model.PSEUDO_USER__VISITOR, autoflush=False)
logged_in = model.User.by_name(model.PSEUDO_USER__LOGGED_IN,
autoflush=False)
if not cls.is_sysadmin(username):
if not cls.is_sysadmin(user):
# This gets the role table the entity is joined to. we
# need to use this in the queries below as if we use
# model.UserObjectRole a cross join happens always
Expand Down
14 changes: 7 additions & 7 deletions ckan/config/environment.py
Expand Up @@ -30,12 +30,12 @@ class _Helpers(object):
def __init__(self, helpers, restrict=True):
functions = {}
allowed = helpers.__allowed_functions__
# list of functions due to be depreciated
self.depreciated = []
# list of functions due to be deprecated
self.deprecated = []

for helper in dir(helpers):
if helper not in allowed:
self.depreciated.append(helper)
self.deprecated.append(helper)
if restrict:
continue
functions[helper] = getattr(helpers, helper)
Expand Down Expand Up @@ -63,14 +63,14 @@ def null_function(cls, *args, **kw):
def __getattr__(self, name):
''' return the function/object requested '''
if name in self.functions:
if name in self.depreciated:
msg = 'Template helper function `%s` is depriciated' % name
if name in self.deprecated:
msg = 'Template helper function `%s` is deprecated' % name
self.log.warn(msg)
return self.functions[name]
else:
if name in self.depreciated:
if name in self.deprecated:
msg = 'Template helper function `%s` is not available ' \
'as it has been depriciated.\nYou can enable it ' \
'as it has been deprecated.\nYou can enable it ' \
'by setting ckan.restrict_template_vars = true ' \
'in your .ini file.' % name
self.log.critical(msg)
Expand Down
5 changes: 3 additions & 2 deletions ckan/config/middleware.py
Expand Up @@ -134,8 +134,9 @@ def make_app(global_conf, full_stack=True, static_files=True, **app_conf):
if asbool(config.get('ckan.page_cache_enabled')):
app = PageCacheMiddleware(app, config)

# Tracking add config option
app = TrackingMiddleware(app, config)
# Tracking
if asbool(config.get('ckan.tracking_enabled', 'false')):
app = TrackingMiddleware(app, config)
return app

class I18nMiddleware(object):
Expand Down
1 change: 0 additions & 1 deletion ckan/config/routing.py
Expand Up @@ -153,7 +153,6 @@ def make_map():
##map.connect('/package/edit/{id}', controller='package_formalchemy', action='edit')

with SubMapper(map, controller='related') as m:
m.connect('related_edit', '/related/{id}/edit', action='edit')
m.connect('related_list', '/dataset/{id}/related', action='list')
m.connect('related_read', '/dataset/{id}/related/{related_id}', action='read')

Expand Down
2 changes: 2 additions & 0 deletions ckan/controllers/admin.py
Expand Up @@ -234,6 +234,8 @@ def action_add_form(users_or_authz_groups):
c.authz_groups = authz_groups
c.authz_groups_role_dict = authz_groups_role_dict

c.are_any_authz_groups = bool(model.Session.query(model.AuthorizationGroup).count())

return render('admin/authz.html')

def trash(self):
Expand Down
2 changes: 1 addition & 1 deletion ckan/controllers/api.py
Expand Up @@ -591,7 +591,7 @@ def group_autocomplete(self):
limit = 20
limit = min(50, limit)

query = model.Group.search_by_name(q, t)
query = model.Group.search_by_name_or_title(q, t)
def convert_to_dict(user):
out = {}
for k in ['id', 'name', 'title']:
Expand Down
3 changes: 2 additions & 1 deletion ckan/controllers/group.py
Expand Up @@ -72,7 +72,8 @@ def index(self):
group_type = self._guess_group_type()

context = {'model': model, 'session': model.Session,
'user': c.user or c.author, 'for_view': True}
'user': c.user or c.author, 'for_view': True,
'with_private': False}

data_dict = {'all_fields': True}

Expand Down
5 changes: 3 additions & 2 deletions ckan/controllers/home.py
Expand Up @@ -14,8 +14,8 @@ class HomeController(BaseController):
repo = model.repo

def __before__(self, action, **env):
BaseController.__before__(self, action, **env)
try:
BaseController.__before__(self, action, **env)
context = {'model':model,'user': c.user or c.author}
ckan.logic.check_access('site_read',context)
except ckan.logic.NotAuthorized:
Expand All @@ -31,7 +31,7 @@ def __before__(self, action, **env):
# TODO: send an email to the admin person (#1285)
else:
raise


def index(self):
try:
Expand All @@ -43,6 +43,7 @@ def index(self):
'facet.field':g.facets,
'rows':0,
'start':0,
'fq': 'capacity:"public"'
}
query = ckan.logic.get_action('package_search')(context,data_dict)
c.package_count = query['count']
Expand Down
8 changes: 5 additions & 3 deletions ckan/controllers/related.py
Expand Up @@ -18,17 +18,19 @@ def list(self, id):

try:
logic.check_access('package_show', context, data_dict)
except logic.NotFound:
base.abort(404, base._('Dataset not found'))
except logic.NotAuthorized:
abort(401, _('Not authorized to see this page'))
base.abort(401, base._('Not authorized to see this page'))

try:
c.pkg_dict = logic.get_action('package_show')(context, data_dict)
c.pkg = context['package']
c.resources_json = h.json.dumps(c.pkg_dict.get('resources',[]))
except logic.NotFound:
abort(404, _('Dataset not found'))
base.abort(404, base._('Dataset not found'))
except logic.NotAuthorized:
abort(401, _('Unauthorized to read package %s') % id)
base.abort(401, base._('Unauthorized to read package %s') % id)

c.related_count = len(c.pkg.related)

Expand Down
14 changes: 11 additions & 3 deletions ckan/controllers/user.py
Expand Up @@ -52,6 +52,11 @@ def _setup_template_variables(self, context):

## end hooks

def _get_repoze_handler(self, handler_name):
'''Returns the URL that repoze.who will respond to and perform a
login or logout.'''
return getattr(request.environ['repoze.who.plugins']['friendlyform'], handler_name)

def index(self):
LIMIT = 20

Expand Down Expand Up @@ -165,7 +170,9 @@ def _save_new(self, context):
return self.new(data_dict, errors, error_summary)
if not c.user:
# Redirect to a URL picked up by repoze.who which performs the login
h.redirect_to('/login_generic?login=%s&password=%s' % (
login_url = self._get_repoze_handler('login_handler_path')
h.redirect_to('%s?login=%s&password=%s' % (
login_url,
str(data_dict['name']),
quote(data_dict['password1'].encode('utf-8'))))
else:
Expand Down Expand Up @@ -257,6 +264,7 @@ def login(self):
g.openid_enabled = False

if not c.user:
c.login_handler = h.url_for(self._get_repoze_handler('login_handler_path'))
return render('user/login.html')
else:
return render('user/logout_first.html')
Expand All @@ -283,10 +291,10 @@ def logged_in(self):
h.redirect_to(locale=lang, controller='user', action='login')

def logout(self):
# save our language in the session so we don't loose it
# save our language in the session so we don't lose it
session['lang'] = request.environ.get('CKAN_LANG')
session.save()
h.redirect_to('/user/logout')
h.redirect_to(self._get_repoze_handler('logout_handler_path'))

def set_lang(self, lang):
# this allows us to set the lang in session. Used for logging
Expand Down
69 changes: 38 additions & 31 deletions ckan/lib/base.py
Expand Up @@ -169,9 +169,11 @@ def _identify_user(self):
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
Expand All @@ -180,8 +182,10 @@ def _identify_user(self):
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 it doesn't check the user (still) exists in our
# database - we need to do that here.
# 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')
Expand Down Expand Up @@ -210,38 +214,41 @@ def __call__(self, environ, start_response):
# 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.
# we do not want to clear cookies when setting the user lang
if not environ.get('PATH_INFO').startswith('/user/set_lang'):
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'):
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()
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()
Expand Down Expand Up @@ -534,7 +541,7 @@ def _prepare_authz_info_for_render(self, user_object_roles):
c.user_role_dict = user_role_dict
c.authz_groups = authz_groups
c.authz_groups_role_dict = authz_groups_role_dict

c.are_any_authz_groups = bool(model.Session.query(model.AuthorizationGroup).count())

# Include the '_' function in the public names
__all__ = [__name for __name in locals().keys() if not __name.startswith('_') \
Expand Down
14 changes: 9 additions & 5 deletions ckan/lib/cli.py
Expand Up @@ -3,11 +3,15 @@
import sys
import logging
from pprint import pprint
import re

import paste.script
from paste.registry import Registry
from paste.script.util.logging_config import fileConfig
import re

#NB No CKAN imports are allowed until after the config file is loaded.
# i.e. do the imports in methods, after _load_config is called.
# Otherwise loggers get disabled.

class MockTranslator(object):
def gettext(self, value):
Expand All @@ -33,11 +37,7 @@ class CkanCommand(paste.script.command.Command):
group_name = 'ckan'

def _load_config(self):
# Avoids vdm logging warning
logging.basicConfig(level=logging.ERROR)

from paste.deploy import appconfig
from ckan.config.environment import load_environment
if not self.options.config:
msg = 'No config file supplied'
raise self.BadCommand(msg)
Expand All @@ -46,6 +46,10 @@ def _load_config(self):
raise AssertionError('Config filename %r does not exist.' % self.filename)
fileConfig(self.filename)
conf = appconfig('config:' + self.filename)
assert 'ckan' not in dir() # otherwise loggers would be disabled
# We have now loaded the config. Now we can import ckan for the
# first time.
from ckan.config.environment import load_environment
load_environment(conf.global_conf, conf.local_conf)

self.registry=Registry()
Expand Down

0 comments on commit 36ba5e6

Please sign in to comment.