--- a/app/soc/cache/base.py Tue Jan 27 22:57:19 2009 +0000
+++ b/app/soc/cache/base.py Tue Jan 27 22:59:01 2009 +0000
@@ -43,7 +43,7 @@
return result
result = func(*args, **kwargs)
- put(result)
+ put(result, *args, **kwargs)
return result
return wrapper
--- a/app/soc/cache/sidebar.py Tue Jan 27 22:57:19 2009 +0000
+++ b/app/soc/cache/sidebar.py Tue Jan 27 22:59:01 2009 +0000
@@ -28,34 +28,33 @@
import soc.cache.base
-def key(user):
+def key(id):
"""Returns the memcache key for the user's sidebar
"""
- return 'sidebar_for_%s' % repr(user)
+ return 'sidebar_for_%s' % repr(id)
-def get():
+def get(id, user):
"""Retrieves the sidebar for the specified user from the memcache
"""
- user = users.get_current_user()
- return memcache.get(key(user))
+ memcache_key = key(id)
+ return memcache.get(memcache_key)
-def put(sidebar):
+def put(sidebar, id, user):
"""Sets the sidebar for the specified user in the memcache
Args:
sidebar: the sidebar to be cached
"""
- # Store sidebar for an hour since new programs might get added
- # etc. etc.
- retention = 60*60
+ # Store sidebar for ten minutes since new programs might get added
+ retention = 10*60
- user = users.get_current_user()
- memcache.add(key(user), sidebar, retention)
+ memcache_key = key(id)
+ memcache.add(memcache_key, sidebar, retention)
def flush(user=None):
@@ -68,7 +67,8 @@
if not user:
user = users.get_current_user()
- memcache.delete(key(user))
+ memcache_key = key(user)
+ memcache.delete(memcache_key)
# define the cache function
--- a/app/soc/views/helper/access.py Tue Jan 27 22:57:19 2009 +0000
+++ b/app/soc/views/helper/access.py Tue Jan 27 22:59:01 2009 +0000
@@ -32,6 +32,7 @@
from google.appengine.api import users
+from google.appengine.api import memcache
from django.core import urlresolvers
from django.utils.translation import ugettext
@@ -117,6 +118,9 @@
base = params.get('rights') if params else None
self.rights = base.rights if base else {}
+ self.id = None
+ self.user = None
+ self.cached_rights = {}
def __setitem__(self, key, value):
"""Sets a value only if no old value exists.
@@ -140,14 +144,81 @@
# Be nice an repack so that it is always a list with tuples
if isinstance(i, tuple):
name, arg = i
- tmp = (getattr(self, name), (arg if isinstance(arg, list) else [arg]))
+ tmp = (name, (arg if isinstance(arg, list) else [arg]))
result.append(tmp)
else:
- tmp = (getattr(self, i), [])
+ tmp = (i, [])
result.append(tmp)
return result
+ def key(self, checker_name):
+ """Returns the key for the specified checker for the current user.
+ """
+
+ return "%s.%s" % (self.id, checker_name)
+
+ def put(self, checker_name, value):
+ """Puts the result for the specified checker in the cache.
+ """
+
+ retention = 30
+
+ memcache_key = self.key(checker_name)
+ memcache.add(memcache_key, value, retention)
+
+ def get(self, checker_name):
+ """Retrieves the result for the specified checker from cache.
+ """
+
+ memcache_key = self.key(checker_name)
+ return memcache.get(memcache_key)
+
+ def doCheck(self, checker_name, django_args, args):
+ """Runs the specified checker with the specified arguments.
+ """
+
+ checker = getattr(self, checker_name)
+ checker(django_args, *args)
+
+ def doCachedCheck(self, checker_name, django_args, args):
+ """Retrieves from cache or runs the specified checker.
+ """
+
+ cached = self.get(checker_name)
+
+ if cached is None:
+ try:
+ self.doCheck(checker_name, django_args, args)
+ self.put(checker_name, True)
+ return
+ except out_of_band.Error, e:
+ self.put(checker_name, e)
+ raise
+
+ if cached is True:
+ return
+
+ # re-raise the cached exception
+ raise cached
+
+ def check(self, use_cache, checker_name, django_args, args):
+ """Runs the checker, optionally using the cache.
+ """
+
+ if use_cache:
+ self.doCachedCheck(checker_name, django_args, args)
+ else:
+ self.doCheck(checker_name, django_args, args)
+
+ def setCurrentUser(self, id, user):
+ """Sets up everything for the current user.
+ """
+
+ self.id = id
+ self.user = user
+ self.cached_rights = {}
+
def checkAccess(self, access_type, django_args):
"""Runs all the defined checks for the specified type.
@@ -167,20 +238,20 @@
value are called.
"""
- self.id = users.get_current_user()
+ use_cache = django_args.get('SIDEBAR_CALLING')
# Call each access checker
- for check, args in self['any_access']:
- check(django_args, *args)
+ for checker_name, args in self['any_access']:
+ self.check(use_cache, checker_name, django_args, args)
if access_type not in self.rights:
- for check, args in self['unspecified']:
- # No checks defined, so do the 'generic' checks and bail out
- check(django_args, *args)
+ # No checks defined, so do the 'generic' checks and bail out
+ for checker_name, args in self['unspecified']:
+ self.check(use_cache, checker_name, django_args, args)
return
- for check, args in self[access_type]:
- check(django_args, *args)
+ for checker_name, args in self[access_type]:
+ self.check(use_cache, checker_name, django_args, args)
def allow(self, django_args):
"""Never raises an alternate HTTP response. (an access no-op, basically).
@@ -253,12 +324,10 @@
self.checkIsLoggedIn(django_args)
- user = user_logic.getForCurrentAccount()
-
- if not user:
+ if not self.user:
raise out_of_band.LoginRequest(message_fmt=DEF_NO_USER_LOGIN_MSG_FMT)
- if user_logic.agreesToSiteToS(user):
+ if user_logic.agreesToSiteToS(self.user):
return
# Would not reach this point of site-wide ToS did not exist, since
--- a/app/soc/views/helper/decorators.py Tue Jan 27 22:57:19 2009 +0000
+++ b/app/soc/views/helper/decorators.py Tue Jan 27 22:59:01 2009 +0000
@@ -97,10 +97,16 @@
check_kwargs = kwargs.copy()
context = responses.getUniversalContext(request)
+ id = context['account']
+ user = context['user']
+
check_kwargs['GET'] = request.GET
check_kwargs['POST'] = request.POST
check_kwargs['context'] = context
+ # reset and pre-fill the Checker's cache
+ rights.setCurrentUser(id, user)
+
# Do the access check dance
try:
rights.checkAccess(access_type, check_kwargs)
--- a/app/soc/views/helper/responses.py Tue Jan 27 22:57:19 2009 +0000
+++ b/app/soc/views/helper/responses.py Tue Jan 27 22:59:01 2009 +0000
@@ -96,21 +96,26 @@
"""
account = users.get_current_user()
+ user = None
+ is_admin = False
context = {}
context['request'] = request
if account:
- context['account'] = account
- context['user'] = soc.logic.models.user.logic.getForFields(
+ user = soc.logic.models.user.logic.getForFields(
{'account': account}, unique=True)
- context['is_admin'] = accounts.isDeveloper(account=account)
+ is_admin = accounts.isDeveloper(account=account)
+
+ context['account'] = account
+ context['user'] = user
+ context['is_admin'] = is_admin
context['is_debug'] = system.isDebug()
context['sign_in'] = users.create_login_url(request.path)
context['sign_out'] = users.create_logout_url(request.path)
- context['sidebar_menu_items'] = sidebar.getSidebar()
+ context['sidebar_menu_items'] = sidebar.getSidebar(account, user)
context['soc_release'] = release.RELEASE_TAG
context['gae_version'] = system.getAppVersion()
--- a/app/soc/views/models/base.py Tue Jan 27 22:57:19 2009 +0000
+++ b/app/soc/views/models/base.py Tue Jan 27 22:59:01 2009 +0000
@@ -726,7 +726,7 @@
return self._params
@decorators.merge_params
- def getSidebarMenus(self, params=None):
+ def getSidebarMenus(self, id, user, params=None):
"""Returns an dictionary with one sidebar entry.
Args:
@@ -738,7 +738,7 @@
of _getSidebarItems on how it uses it.
"""
- return sitemap.sidebar.getSidebarMenus(params=params)
+ return sitemap.sidebar.getSidebarMenus(id, user, params=params)
@decorators.merge_params
def getDjangoURLPatterns(self, params=None):
--- a/app/soc/views/models/group.py Tue Jan 27 22:57:19 2009 +0000
+++ b/app/soc/views/models/group.py Tue Jan 27 22:59:01 2009 +0000
@@ -262,7 +262,7 @@
role_views = self._params['role_views']
role_views[role_name] = role_view
- def getExtraMenus(self, params=None):
+ def getExtraMenus(self, id, user, params=None):
"""Returns the extra menu's for this view.
A menu item is generated for each group that the user has an active
@@ -276,11 +276,8 @@
params = dicts.merge(params, self._params)
logic = params['logic']
- # get the current user
- user_entity = user_logic.logic.getForCurrentAccount()
-
# set fields to match every active role this user has
- fields = {'user': user_entity,
+ fields = {'user': user,
'state' : 'active'}
# get the role views and start filling group_entities
--- a/app/soc/views/models/program.py Tue Jan 27 22:57:19 2009 +0000
+++ b/app/soc/views/models/program.py Tue Jan 27 22:59:01 2009 +0000
@@ -116,7 +116,7 @@
timeline = timeline_logic.updateOrCreateFromFields(properties, properties)
return timeline
- def getExtraMenus(self, params=None):
+ def getExtraMenus(self, id, user, params=None):
"""Returns the extra menu's for this view.
A menu item is generated for each program that is currently
--- a/app/soc/views/models/site.py Tue Jan 27 22:57:19 2009 +0000
+++ b/app/soc/views/models/site.py Tue Jan 27 22:59:01 2009 +0000
@@ -87,13 +87,13 @@
super(View, self).__init__(params=params)
- def getSidebarMenus(self, params=None):
+ def getSidebarMenus(self, id, user, params=None):
"""See base.View.getSidebarMenus.
Returns a custom sidebar entry for the 'site' singleton.
"""
- entity = self._logic.getFromFields(link_id=self._logic.DEF_SITE_LINK_ID)
+ entity = self._logic.getSingleton()
submenus = []
@@ -104,7 +104,7 @@
new_params['sidebar_additional'] = submenus
params = dicts.merge(params, new_params)
- return super(View, self).getSidebarMenus(params=params)
+ return super(View, self).getSidebarMenus(id, user, params=params)
def mainPublic(self, request, page_name=None, **kwargs):
"""Displays the main site settings page.
--- a/app/soc/views/models/user_self.py Tue Jan 27 22:57:19 2009 +0000
+++ b/app/soc/views/models/user_self.py Tue Jan 27 22:59:01 2009 +0000
@@ -252,14 +252,12 @@
super(View, self)._editPost(request, entity, fields)
- def getSidebarMenus(self, params=None):
+ def getSidebarMenus(self, id, user, params=None):
"""See base.View.getSidebarMenus().
"""
link_title = ugettext('Notifications')
- user = user_logic.getForCurrentAccount()
-
filter = {
'scope': user,
'unread': True,
@@ -279,7 +277,7 @@
params = dicts.merge(params, new_params)
- return super(View, self).getSidebarMenus(params=params)
+ return super(View, self).getSidebarMenus(id, user, params=params)
view = View()
--- a/app/soc/views/out_of_band.py Tue Jan 27 22:57:19 2009 +0000
+++ b/app/soc/views/out_of_band.py Tue Jan 27 22:59:01 2009 +0000
@@ -32,7 +32,7 @@
TEMPLATE_NAME = 'error.html'
DEF_TEMPLATE = 'soc/error.html'
- def __init__(self, message_fmt, context=None, **response_args):
+ def __init__(self, message_fmt=None, context=None, **response_args):
"""Constructor used to set response message and HTTP response arguments.
Args:
@@ -46,6 +46,9 @@
set the HTTP status code for the response
"""
+ if not message_fmt:
+ message_fmt = ""
+
self.message_fmt = message_fmt
self.context = context
self.response_args = response_args
--- a/app/soc/views/sitemap/sidebar.py Tue Jan 27 22:57:19 2009 +0000
+++ b/app/soc/views/sitemap/sidebar.py Tue Jan 27 22:59:01 2009 +0000
@@ -44,14 +44,14 @@
@soc.cache.sidebar.cache
-def getSidebar():
+def getSidebar(id, user):
"""Constructs a sidebar for the current user.
"""
sidebar = []
for callback in SIDEBAR:
- menus = callback()
+ menus = callback(id, user)
for menu in (menus if menus else []):
sidebar.append(menu)
@@ -102,7 +102,7 @@
return result
-def getSidebarMenu(items, params):
+def getSidebarMenu(id, user, items, params):
"""Returns an dictionary with one sidebar entry.
Items is expected to be a tuple with an url, a menu_text, and an
@@ -138,6 +138,9 @@
args = SIDEBAR_ACCESS_ARGS
kwargs = SIDEBAR_ACCESS_KWARGS
+ # reset and pre-fill the Checker's cache
+ rights.setCurrentUser(id, user)
+
for url, menu_text, access_type in items:
try:
rights.checkAccess(access_type, kwargs)
@@ -148,7 +151,7 @@
return submenus
-def getSidebarMenus(params=None):
+def getSidebarMenus(id, user, params=None):
"""Constructs the default sidebar menu for a View.
Calls getSidebarItems to retrieve the items that should be in the
@@ -160,7 +163,7 @@
"""
items = getSidebarItems(params)
- submenus = getSidebarMenu(items, params)
+ submenus = getSidebarMenu(id, user, items, params)
if not submenus:
return