app/soc/views/helper/access.py
changeset 1017 6ad4fdb48840
parent 1016 15a2f644725f
child 1023 d849b47645f9
equal deleted inserted replaced
1016:15a2f644725f 1017:6ad4fdb48840
    30   '"Pawel Solyga" <pawel.solyga@gmail.com>',
    30   '"Pawel Solyga" <pawel.solyga@gmail.com>',
    31   ]
    31   ]
    32 
    32 
    33 
    33 
    34 from google.appengine.api import users
    34 from google.appengine.api import users
       
    35 from google.appengine.api import memcache
    35 
    36 
    36 from django.core import urlresolvers
    37 from django.core import urlresolvers
    37 from django.utils.translation import ugettext
    38 from django.utils.translation import ugettext
    38 
    39 
    39 from soc.logic import accounts
    40 from soc.logic import accounts
   115     """Adopts base.rights as rights if base is set.
   116     """Adopts base.rights as rights if base is set.
   116     """
   117     """
   117 
   118 
   118     base = params.get('rights') if params else None
   119     base = params.get('rights') if params else None
   119     self.rights = base.rights if base else {}
   120     self.rights = base.rights if base else {}
       
   121     self.id = None
       
   122     self.user = None
       
   123     self.cached_rights = {}
   120 
   124 
   121   def __setitem__(self, key, value):
   125   def __setitem__(self, key, value):
   122     """Sets a value only if no old value exists.
   126     """Sets a value only if no old value exists.
   123     """
   127     """
   124 
   128 
   138 
   142 
   139     for i in self.rights.get(key, []):
   143     for i in self.rights.get(key, []):
   140       # Be nice an repack so that it is always a list with tuples
   144       # Be nice an repack so that it is always a list with tuples
   141       if isinstance(i, tuple):
   145       if isinstance(i, tuple):
   142         name, arg = i
   146         name, arg = i
   143         tmp = (getattr(self, name), (arg if isinstance(arg, list) else [arg]))
   147         tmp = (name, (arg if isinstance(arg, list) else [arg]))
   144         result.append(tmp)
   148         result.append(tmp)
   145       else:
   149       else:
   146         tmp = (getattr(self, i), [])
   150         tmp = (i, [])
   147         result.append(tmp)
   151         result.append(tmp)
   148 
   152 
   149     return result
   153     return result
       
   154 
       
   155   def key(self, checker_name):
       
   156     """Returns the key for the specified checker for the current user.
       
   157     """
       
   158 
       
   159     return "%s.%s" % (self.id, checker_name)
       
   160 
       
   161   def put(self, checker_name, value):
       
   162     """Puts the result for the specified checker in the cache.
       
   163     """
       
   164 
       
   165     retention = 30
       
   166 
       
   167     memcache_key = self.key(checker_name)
       
   168     memcache.add(memcache_key, value, retention)
       
   169 
       
   170   def get(self, checker_name):
       
   171     """Retrieves the result for the specified checker from cache.
       
   172     """
       
   173 
       
   174     memcache_key = self.key(checker_name)
       
   175     return memcache.get(memcache_key)
       
   176 
       
   177   def doCheck(self, checker_name, django_args, args):
       
   178     """Runs the specified checker with the specified arguments.
       
   179     """
       
   180 
       
   181     checker = getattr(self, checker_name)
       
   182     checker(django_args, *args)
       
   183 
       
   184   def doCachedCheck(self, checker_name, django_args, args):
       
   185     """Retrieves from cache or runs the specified checker.
       
   186     """
       
   187 
       
   188     cached = self.get(checker_name)
       
   189 
       
   190     if cached is None:
       
   191       try:
       
   192         self.doCheck(checker_name, django_args, args)
       
   193         self.put(checker_name, True)
       
   194         return
       
   195       except out_of_band.Error, e:
       
   196         self.put(checker_name, e)
       
   197         raise
       
   198 
       
   199     if cached is True:
       
   200       return
       
   201 
       
   202     # re-raise the cached exception
       
   203     raise cached
       
   204 
       
   205   def check(self, use_cache, checker_name, django_args, args):
       
   206     """Runs the checker, optionally using the cache.
       
   207     """
       
   208 
       
   209     if use_cache:
       
   210       self.doCachedCheck(checker_name, django_args, args)
       
   211     else:
       
   212       self.doCheck(checker_name, django_args, args)
       
   213 
       
   214   def setCurrentUser(self, id, user):
       
   215     """Sets up everything for the current user.
       
   216     """
       
   217 
       
   218     self.id = id
       
   219     self.user = user
       
   220     self.cached_rights = {}
   150 
   221 
   151   def checkAccess(self, access_type, django_args):
   222   def checkAccess(self, access_type, django_args):
   152     """Runs all the defined checks for the specified type.
   223     """Runs all the defined checks for the specified type.
   153 
   224 
   154     Args:
   225     Args:
   165       the functions in the 'unspecified' value are called. When the specified
   236       the functions in the 'unspecified' value are called. When the specified
   166       type _is_ in the rights dictionary, all the functions in that access_type's
   237       type _is_ in the rights dictionary, all the functions in that access_type's
   167       value are called.
   238       value are called.
   168     """
   239     """
   169 
   240 
   170     self.id = users.get_current_user()
   241     use_cache = django_args.get('SIDEBAR_CALLING')
   171 
   242 
   172     # Call each access checker
   243     # Call each access checker
   173     for check, args in self['any_access']:
   244     for checker_name, args in self['any_access']:
   174       check(django_args, *args)
   245       self.check(use_cache, checker_name, django_args, args)
   175 
   246 
   176     if access_type not in self.rights:
   247     if access_type not in self.rights:
   177       for check, args in self['unspecified']:
   248       # No checks defined, so do the 'generic' checks and bail out
   178         # No checks defined, so do the 'generic' checks and bail out
   249       for checker_name, args in self['unspecified']:
   179         check(django_args, *args)
   250         self.check(use_cache, checker_name, django_args, args)
   180       return
   251       return
   181 
   252 
   182     for check, args in self[access_type]:
   253     for checker_name, args in self[access_type]:
   183       check(django_args, *args)
   254       self.check(use_cache, checker_name, django_args, args)
   184 
   255 
   185   def allow(self, django_args):
   256   def allow(self, django_args):
   186     """Never raises an alternate HTTP response.  (an access no-op, basically).
   257     """Never raises an alternate HTTP response.  (an access no-op, basically).
   187 
   258 
   188     Args:
   259     Args:
   251       * if User has not agreed to the site-wide ToS, if one exists
   322       * if User has not agreed to the site-wide ToS, if one exists
   252     """
   323     """
   253 
   324 
   254     self.checkIsLoggedIn(django_args)
   325     self.checkIsLoggedIn(django_args)
   255 
   326 
   256     user = user_logic.getForCurrentAccount()
   327     if not self.user:
   257 
       
   258     if not user:
       
   259       raise out_of_band.LoginRequest(message_fmt=DEF_NO_USER_LOGIN_MSG_FMT)
   328       raise out_of_band.LoginRequest(message_fmt=DEF_NO_USER_LOGIN_MSG_FMT)
   260 
   329 
   261     if user_logic.agreesToSiteToS(user):
   330     if user_logic.agreesToSiteToS(self.user):
   262       return
   331       return
   263 
   332 
   264     # Would not reach this point of site-wide ToS did not exist, since
   333     # Would not reach this point of site-wide ToS did not exist, since
   265     # agreesToSiteToS() call above always returns True if no ToS is in effect.
   334     # agreesToSiteToS() call above always returns True if no ToS is in effect.
   266     login_msg_fmt = DEF_AGREE_TO_TOS_MSG_FMT % {
   335     login_msg_fmt = DEF_AGREE_TO_TOS_MSG_FMT % {