app/soc/views/helper/access.py
changeset 972 43018f61b481
parent 970 8b5611d5b053
child 974 2f86cbc90b65
equal deleted inserted replaced
971:1d852b58b182 972:43018f61b481
    68 
    68 
    69 DEF_LOGOUT_MSG_FMT = ugettext(
    69 DEF_LOGOUT_MSG_FMT = ugettext(
    70     'Please <a href="%(sign_out)s">sign out</a> in order to view this page')
    70     'Please <a href="%(sign_out)s">sign out</a> in order to view this page')
    71 
    71 
    72 
    72 
    73 def checkAccess(access_type, request, rights, args=None, kwargs=None):
    73 def checkAccess(access_type, rights, kwargs=None):
    74   """Runs all the defined checks for the specified type.
    74   """Runs all the defined checks for the specified type.
    75 
    75 
    76   Args:
    76   Args:
    77     access_type: the type of request (such as 'list' or 'edit')
    77     access_type: the type of request (such as 'list' or 'edit')
    78     request: the Django request object
       
    79     rights: a dictionary containing access check functions
    78     rights: a dictionary containing access check functions
       
    79     kwargs: a dictionary with django's arguments
    80 
    80 
    81   Rights usage: 
    81   Rights usage: 
    82     The rights dictionary is used to check if the current user is allowed 
    82     The rights dictionary is used to check if the current user is allowed 
    83     to view the page specified. The functions defined in this dictionary 
    83     to view the page specified. The functions defined in this dictionary 
    84     are always called with the django request object as argument. On any 
    84     are always called with the provided kwargs dictionary as argument. On any
    85     request, regardless of what type, the functions in the 'any_access' value 
    85     request, regardless of what type, the functions in the 'any_access' value
    86     are called. If the specified type is not in the rights dictionary, all 
    86     are called. If the specified type is not in the rights dictionary, all
    87     the functions in the 'unspecified' value are called. When the specified 
    87     the functions in the 'unspecified' value are called. When the specified
    88     type _is_ in the rights dictionary, all the functions in that access_type's 
    88     type _is_ in the rights dictionary, all the functions in that access_type's
    89     value are called.
    89     value are called.
    90 
       
    91   Returns:
       
    92     True: If all the required access checks have been made successfully
       
    93     False: If a check failed, in this case self._response will contain
       
    94       the response provided by the failed access check.
       
    95   """
    90   """
    96 
    91 
    97   # Call each access checker
    92   # Call each access checker
    98   for check in rights['any_access']:
    93   for check in rights['any_access']:
    99     check(request, args, kwargs)
    94     check(kwargs)
   100 
    95 
   101   if access_type not in rights:
    96   if access_type not in rights:
   102     for check in rights['unspecified']:
    97     for check in rights['unspecified']:
   103       # No checks defined, so do the 'generic' checks and bail out
    98       # No checks defined, so do the 'generic' checks and bail out
   104       check(request, args, kwargs)
    99       check(kwargs)
   105     return
   100     return
   106 
   101 
   107   for check in rights[access_type]:
   102   for check in rights[access_type]:
   108     check(request, args, kwargs)
   103     check(kwargs)
   109 
   104 
   110 
   105 
   111 def allow(request, args, kwargs):
   106 def allow(kwargs):
   112   """Never raises an alternate HTTP response.  (an access no-op, basically).
   107   """Never raises an alternate HTTP response.  (an access no-op, basically).
   113 
   108 
   114   Args:
   109   Args:
   115     request: a Django HTTP request
   110     kwargs: a dictionary with django's arguments
   116   """
   111   """
       
   112 
   117   return
   113   return
   118 
   114 
   119 
   115 
   120 def deny(request, args, kwargs):
   116 def deny(kwargs):
   121   """Always raises an alternate HTTP response.
   117   """Always raises an alternate HTTP response.
   122 
   118 
   123   Args:
   119   Args:
   124     request: a Django HTTP request
   120     kwargs: a dictionary with django's arguments
   125 
   121 
   126   Raises:
   122   Raises:
   127     always raises AccessViolationResponse if called
   123     always raises AccessViolationResponse if called
   128   """
   124   """
   129 
   125 
   130   import soc.views.helper.responses
   126   import soc.views.helper.responses
   131 
   127 
   132   if kwargs.get('SIDEBAR_CALLING', False):
   128   kwargs.get('context', {})
   133     context = {}
       
   134   else:
       
   135     context = soc.views.helper.responses.getUniversalContext(request)
       
   136 
       
   137   context['title'] = 'Access denied'
   129   context['title'] = 'Access denied'
   138 
   130 
   139   raise out_of_band.AccessViolation(DEF_PAGE_DENIED_MSG, context=context)
   131   raise out_of_band.AccessViolation(DEF_PAGE_DENIED_MSG, context=context)
   140 
   132 
   141 
   133 
   142 def checkIsLoggedIn(request, args, kwargs):
   134 def checkIsLoggedIn(kwargs):
   143   """Raises an alternate HTTP response if Google Account is not logged in.
   135   """Raises an alternate HTTP response if Google Account is not logged in.
   144 
   136 
   145   Args:
   137   Args:
   146     request: a Django HTTP request
   138     kwargs: a dictionary with django's arguments
   147 
   139 
   148   Raises:
   140   Raises:
   149     AccessViolationResponse:
   141     AccessViolationResponse:
   150     * if no Google Account is even logged in
   142     * if no Google Account is even logged in
   151   """
   143   """
       
   144 
   152   if users.get_current_user():
   145   if users.get_current_user():
   153     return
   146     return
   154 
   147 
   155   raise out_of_band.LoginRequest()
   148   raise out_of_band.LoginRequest()
   156 
   149 
   157 
   150 
   158 def checkNotLoggedIn(request, args, kwargs):
   151 def checkNotLoggedIn(kwargs):
   159   """Raises an alternate HTTP response if Google Account is logged in.
   152   """Raises an alternate HTTP response if Google Account is logged in.
   160 
   153 
   161   Args:
   154   Args:
   162     request: a Django HTTP request
   155     kwargs: a dictionary with django's arguments
   163 
   156 
   164   Raises:
   157   Raises:
   165     AccessViolationResponse:
   158     AccessViolationResponse:
   166     * if a Google Account is currently logged in
   159     * if a Google Account is currently logged in
   167   """
   160   """
       
   161   
   168   if not users.get_current_user():
   162   if not users.get_current_user():
   169     return
   163     return
   170 
   164 
   171   raise out_of_band.LoginRequest(message_fmt=DEF_LOGOUT_MSG_FMT)
   165   raise out_of_band.LoginRequest(message_fmt=DEF_LOGOUT_MSG_FMT)
   172 
   166 
   173 
   167 
   174 def checkIsUser(request, args, kwargs):
   168 def checkIsUser(kwargs):
   175   """Raises an alternate HTTP response if Google Account has no User entity.
   169   """Raises an alternate HTTP response if Google Account has no User entity.
   176 
   170 
   177   Args:
   171   Args:
   178     request: a Django HTTP request
   172     kwargs: a dictionary with django's arguments
   179 
   173 
   180   Raises:
   174   Raises:
   181     AccessViolationResponse:
   175     AccessViolationResponse:
   182     * if no User exists for the logged-in Google Account, or
   176     * if no User exists for the logged-in Google Account, or
   183     * if no Google Account is logged in at all
   177     * if no Google Account is logged in at all
   184   """
   178   """
   185   checkIsLoggedIn(request, args, kwargs)
   179 
   186 
   180   checkIsLoggedIn(kwargs)
   187   user = user_logic.getForFields({'account': users.get_current_user()},
   181 
   188                                  unique=True)
   182   user = user_logic.getForCurrentAccount()
   189 
   183 
   190   if user:
   184   if user:
   191     return
   185     return
   192 
   186 
   193   raise out_of_band.LoginRequest(message_fmt=DEF_NO_USER_LOGIN_MSG_FMT)
   187   raise out_of_band.LoginRequest(message_fmt=DEF_NO_USER_LOGIN_MSG_FMT)
   194 
   188 
   195 
   189 
   196 def checkAgreesToSiteToS(request, args, kwargs):
   190 def checkAgreesToSiteToS(kwargs):
   197   """Raises an alternate HTTP response if User has not agreed to site-wide ToS.
   191   """Raises an alternate HTTP response if User has not agreed to site-wide ToS.
   198 
   192 
   199   Args:
   193   Args:
   200     request: a Django HTTP request
   194     kwargs: a dictionary with django's arguments
   201 
   195 
   202   Raises:
   196   Raises:
   203     AccessViolationResponse:
   197     AccessViolationResponse:
   204     * if User has not agreed to the site-wide ToS, or
   198     * if User has not agreed to the site-wide ToS, or
   205     * if no User exists for the logged-in Google Account, or
   199     * if no User exists for the logged-in Google Account, or
   206     * if no Google Account is logged in at all
   200     * if no Google Account is logged in at all
   207   """
   201   """
   208   checkIsUser(request, args, kwargs)
   202 
       
   203   checkIsUser(kwargs)
   209 
   204 
   210   user = user_logic.getForCurrentAccount()
   205   user = user_logic.getForCurrentAccount()
   211   
   206   
   212   if user_logic.agreesToSiteToS(user):
   207   if user_logic.agreesToSiteToS(user):
   213     return
   208     return
   218       'tos_link': redirects.getToSRedirect(site_logic.getSingleton())}
   213       'tos_link': redirects.getToSRedirect(site_logic.getSingleton())}
   219 
   214 
   220   raise out_of_band.LoginRequest(message_fmt=login_msg_fmt)
   215   raise out_of_band.LoginRequest(message_fmt=login_msg_fmt)
   221 
   216 
   222 
   217 
   223 def checkIsDeveloper(request, args, kwargs):
   218 def checkIsDeveloper(kwargs):
   224   """Raises an alternate HTTP response if Google Account is not a Developer.
   219   """Raises an alternate HTTP response if Google Account is not a Developer.
   225 
   220 
   226   Args:
   221   Args:
   227     request: a Django HTTP request
   222     kwargs: a dictionary with django's arguments
   228 
   223 
   229   Raises:
   224   Raises:
   230     AccessViolationResponse:
   225     AccessViolationResponse:
   231     * if User is not a Developer, or
   226     * if User is not a Developer, or
   232     * if no User exists for the logged-in Google Account, or
   227     * if no User exists for the logged-in Google Account, or
   233     * if no Google Account is logged in at all
   228     * if no Google Account is logged in at all
   234   """
   229   """
   235 
   230 
   236   checkAgreesToSiteToS(request, args, kwargs)
   231   checkAgreesToSiteToS(kwargs)
   237 
   232 
   238   if accounts.isDeveloper(account=users.get_current_user()):
   233   if accounts.isDeveloper(account=users.get_current_user()):
   239     return
   234     return
   240 
   235 
   241   login_message_fmt = DEF_DEV_LOGOUT_LOGIN_MSG_FMT % {
   236   login_message_fmt = DEF_DEV_LOGOUT_LOGIN_MSG_FMT % {
   246 
   241 
   247 def checkCanCreateFromRequest(role_name):
   242 def checkCanCreateFromRequest(role_name):
   248   """Raises an alternate HTTP response if the specified request does not exist
   243   """Raises an alternate HTTP response if the specified request does not exist
   249      or if it's state is not group_accepted. 
   244      or if it's state is not group_accepted. 
   250   """
   245   """
   251   def wrapper(request, args, kwargs):
   246 
   252     checkAgreesToSiteToS(request, args, kwargs)
   247   def wrapper(kwargs):
       
   248     checkAgreesToSiteToS(kwargs)
   253 
   249 
   254     user_entity = user_logic.getForCurrentAccount()
   250     user_entity = user_logic.getForCurrentAccount()
   255 
   251 
   256     if user_entity.link_id != kwargs['link_id']:
   252     if user_entity.link_id != kwargs['link_id']:
   257       deny(request, args, kwargs)
   253       deny(kwargs)
   258 
   254 
   259     fields = {'link_id': kwargs['link_id'],
   255     fields = {'link_id': kwargs['link_id'],
   260         'scope_path': kwargs['scope_path'],
   256         'scope_path': kwargs['scope_path'],
   261         'role': role_name}
   257         'role': role_name}
   262 
   258 
   263     request_entity = request_logic.getFromFieldsOr404(**fields)
   259     request_entity = request_logic.getFromFieldsOr404(**fields)
   264 
   260 
   265     if request_entity.state != 'group_accepted':
   261     if request_entity.state != 'group_accepted':
   266       # TODO tell the user that this request has not been accepted yet
   262       # TODO tell the user that this request has not been accepted yet
   267       deny(request, args, kwargs)
   263       deny(kwargs)
   268 
   264 
   269     return
   265     return
       
   266 
   270   return wrapper
   267   return wrapper
   271 
   268 
   272 
   269 
   273 def checkCanProcessRequest(role_name):
   270 def checkCanProcessRequest(role_name):
   274   """Raises an alternate HTTP response if the specified request does not exist
   271   """Raises an alternate HTTP response if the specified request does not exist
   275      or if it's state is completed or denied. 
   272      or if it's state is completed or denied. 
   276   """
   273   """
   277   def wrapper(request, args, kwargs):
   274 
       
   275   def wrapper(kwargs):
   278 
   276 
   279     fields = {'link_id': kwargs['link_id'],
   277     fields = {'link_id': kwargs['link_id'],
   280         'scope_path': kwargs['scope_path'],
   278         'scope_path': kwargs['scope_path'],
   281         'role': role_name}
   279         'role': role_name}
   282 
   280 
   283     request_entity = request_logic.getFromFieldsOr404(**fields)
   281     request_entity = request_logic.getFromFieldsOr404(**fields)
   284 
   282 
   285     if request_entity.state in ['completed', 'denied']:
   283     if request_entity.state in ['completed', 'denied']:
   286       # TODO tell the user that this request has been processed
   284       # TODO tell the user that this request has been processed
   287       deny(request, args, kwargs)
   285       deny(kwargs)
   288 
   286 
   289     return
   287     return
       
   288   
   290   return wrapper
   289   return wrapper
   291 
   290 
   292 
   291 
   293 def checkIsMyGroupAcceptedRequest(request, args, kwargs):
   292 def checkIsMyGroupAcceptedRequest(kwargs):
   294   """Raises an alternate HTTP response if the specified request does not exist
   293   """Raises an alternate HTTP response if the specified request does not exist
   295      or if it's state is not group_accepted.
   294      or if it's state is not group_accepted.
   296   """
   295   """
   297   checkAgreesToSiteToS(request, args, kwargs)
   296 
       
   297   checkAgreesToSiteToS(kwargs)
   298 
   298 
   299   user_entity = user_logic.getForCurrentAccount()
   299   user_entity = user_logic.getForCurrentAccount()
   300 
   300 
   301   if user_entity.link_id != kwargs['link_id']:
   301   if user_entity.link_id != kwargs['link_id']:
   302     # not the current user's request
   302     # not the current user's request
   303     return deny(request, args, kwargs)
   303     return deny(kwargs)
   304 
   304 
   305   fields = {'link_id': kwargs['link_id'],
   305   fields = {'link_id': kwargs['link_id'],
   306             'scope_path': kwargs['scope_path'],
   306             'scope_path': kwargs['scope_path'],
   307             'role': kwargs['role']}
   307             'role': kwargs['role']}
   308 
   308 
   309   request_entity = request_logic.getForFields(fields, unique=True)
   309   request_entity = request_logic.getForFields(fields, unique=True)
   310 
   310 
   311   if not request_entity:
   311   if not request_entity:
   312     # TODO return 404
   312     # TODO return 404
   313     return deny(request, args, kwargs)
   313     return deny(kwargs)
   314 
   314 
   315   if request_entity.state != 'group_accepted':
   315   if request_entity.state != 'group_accepted':
   316     return deny(request, args, kwargs)
   316     return deny(kwargs)
   317 
   317 
   318   return
   318   return
   319 
   319 
   320 
   320 
   321 def checkIsHost(request, args, kwargs):
   321 def checkIsHost(kwargs):
   322   """Raises an alternate HTTP response if Google Account has no Host entity.
   322   """Raises an alternate HTTP response if Google Account has no Host entity.
   323 
   323 
   324   Args:
   324   Args:
   325     request: a Django HTTP request
   325     request: a Django HTTP request
   326 
   326 
   332     * if the user is not even logged in
   332     * if the user is not even logged in
   333   """
   333   """
   334 
   334 
   335   try:
   335   try:
   336     # if the current user is invited to create a host profile we allow access
   336     # if the current user is invited to create a host profile we allow access
   337     checkIsDeveloper(request, args, kwargs)
   337     checkIsDeveloper(kwargs)
   338     return
   338     return
   339   except out_of_band.Error:
   339   except out_of_band.Error:
   340     pass
   340     pass
   341 
   341 
   342   checkAgreesToSiteToS(request, args, kwargs)
   342   checkAgreesToSiteToS(kwargs)
   343 
   343 
   344   user = user_logic.getForFields({'account': users.get_current_user()},
   344   user = user_logic.getForCurrentAccount()
   345                                  unique=True)
       
   346 
   345 
   347   fields = {'user': user,
   346   fields = {'user': user,
   348             'state': 'active'}
   347             'state': 'active'}
   349 
   348 
   350   host = host_logic.getForFields(fields, unique=True)
   349   host = host_logic.getForFields(fields, unique=True)
   356       'role': 'a Program Administrator '}
   355       'role': 'a Program Administrator '}
   357 
   356 
   358   raise out_of_band.LoginRequest(message_fmt=login_message_fmt)
   357   raise out_of_band.LoginRequest(message_fmt=login_message_fmt)
   359 
   358 
   360 
   359 
   361 def checkIsHostForProgram(request, args, kwargs):
   360 def checkIsHostForProgram(kwargs):
   362   """Raises an alternate HTTP response if Google Account has no Host entity
   361   """Raises an alternate HTTP response if Google Account has no Host entity
   363      for the specified program.
   362      for the specified program.
   364 
   363 
   365   Args:
   364   Args:
   366     request: a Django HTTP request
   365     request: a Django HTTP request
   370     * if User is not already a Host for the specified program, or
   369     * if User is not already a Host for the specified program, or
   371     * if User has not agreed to the site-wide ToS, or
   370     * if User has not agreed to the site-wide ToS, or
   372     * if no User exists for the logged-in Google Account, or
   371     * if no User exists for the logged-in Google Account, or
   373     * if the user is not even logged in
   372     * if the user is not even logged in
   374   """
   373   """
   375   checkAgreesToSiteToS(request, args, kwargs)
   374 
   376 
   375   checkAgreesToSiteToS(kwargs)
   377   user = user_logic.getForFields({'account': users.get_current_user()},
   376 
   378                                  unique=True)
   377   user = user_logic.getForCurrentAccount()
   379 
   378 
   380   fields = {'user': user,
   379   fields = {'user': user,
   381             'scope_path': kwargs['scope_path'],
   380             'scope_path': kwargs['scope_path'],
   382             'state': 'active'}
   381             'state': 'active'}
   383 
   382 
   390       'role': 'a Program Administrator '}
   389       'role': 'a Program Administrator '}
   391 
   390 
   392   raise out_of_band.LoginRequest(message_fmt=login_message_fmt)
   391   raise out_of_band.LoginRequest(message_fmt=login_message_fmt)
   393 
   392 
   394 
   393 
   395 def checkIsClubAdminForClub(request, args, kwargs):
   394 def checkIsClubAdminForClub(kwargs):
   396   """Returns an alternate HTTP response if Google Account has no Club Admin
   395   """Returns an alternate HTTP response if Google Account has no Club Admin
   397      entity for the specified club.
   396      entity for the specified club.
   398 
   397 
   399   Args:
   398   Args:
   400     request: a Django HTTP request
   399     kwargs: a dictionary with django's arguments
   401 
   400 
   402    Raises:
   401    Raises:
   403      AccessViolationResponse: if the required authorization is not met
   402      AccessViolationResponse: if the required authorization is not met
   404 
   403 
   405   Returns:
   404   Returns:
   408     should be returned by the calling view.
   407     should be returned by the calling view.
   409   """
   408   """
   410 
   409 
   411   try:
   410   try:
   412     # if the current user is invited to create a host profile we allow access
   411     # if the current user is invited to create a host profile we allow access
   413     checkIsDeveloper(request, args, kwargs)
   412     checkIsDeveloper(kwargs)
   414     return
   413     return
   415   except out_of_band.Error:
   414   except out_of_band.Error:
   416     pass
   415     pass
   417 
   416 
   418   checkAgreesToSiteToS(request, args, kwargs)
   417   checkAgreesToSiteToS(kwargs)
   419 
   418 
   420   user = user_logic.getForCurrentAccount()
   419   user = user_logic.getForCurrentAccount()
   421 
   420 
   422   if kwargs.get('scope_path'):
   421   if kwargs.get('scope_path'):
   423     scope_path = kwargs['scope_path']
   422     scope_path = kwargs['scope_path']
   442 def checkIsApplicationAccepted(app_logic):
   441 def checkIsApplicationAccepted(app_logic):
   443   """Returns an alternate HTTP response if Google Account has no Club App
   442   """Returns an alternate HTTP response if Google Account has no Club App
   444      entity for the specified Club.
   443      entity for the specified Club.
   445 
   444 
   446   Args:
   445   Args:
   447     request: a Django HTTP request
   446     kwargs: a dictionary with django's arguments
   448 
   447 
   449    Raises:
   448    Raises:
   450      AccessViolationResponse: if the required authorization is not met
   449      AccessViolationResponse: if the required authorization is not met
   451 
   450 
   452   Returns:
   451   Returns:
   453     None if Club App  exists for the specified program, or a subclass
   452     None if Club App  exists for the specified program, or a subclass
   454     of django.http.HttpResponse which contains the alternate response
   453     of django.http.HttpResponse which contains the alternate response
   455     should be returned by the calling view.
   454     should be returned by the calling view.
   456   """
   455   """
   457 
   456 
   458   def wrapper(request, args, kwargs):
   457   def wrapper(kwargs):
   459     try:
   458     try:
   460       # if the current user is a developer we allow access
   459       # if the current user is a developer we allow access
   461       checkIsDeveloper(request, args, kwargs)
   460       checkIsDeveloper(kwargs)
   462       return
   461       return
   463     except out_of_band.Error:
   462     except out_of_band.Error:
   464       pass
   463       pass
   465 
   464 
   466     checkAgreesToSiteToS(request, args, kwargs)
   465     checkAgreesToSiteToS(kwargs)
   467 
   466 
   468     user = user_logic.getForCurrentAccount()
   467     user = user_logic.getForCurrentAccount()
   469 
   468 
   470     properties = {
   469     properties = {
   471         'applicant': user,
   470         'applicant': user,
   476 
   475 
   477     if application:
   476     if application:
   478       return
   477       return
   479 
   478 
   480     # TODO(srabbelier) Make this give a proper error message
   479     # TODO(srabbelier) Make this give a proper error message
   481     deny(request, args, kwargs)
   480     deny(kwargs)
   482 
   481 
   483   return wrapper
   482   return wrapper
   484 
   483 
   485 
   484 
   486 def checkIsMyNotification(request, args, kwargs):
   485 def checkIsMyNotification(kwargs):
   487   """Returns an alternate HTTP response if this request is for 
   486   """Returns an alternate HTTP response if this request is for 
   488      a Notification belonging to the current user.
   487      a Notification belonging to the current user.
   489 
   488 
   490   Args:
   489   Args:
   491     request: a Django HTTP request
   490     kwargs: a dictionary with django's arguments
   492 
   491 
   493    Raises:
   492    Raises:
   494      AccessViolationResponse: if the required authorization is not met
   493      AccessViolationResponse: if the required authorization is not met
   495 
   494 
   496   Returns:
   495   Returns:
   497     None if the current User is allowed to access this Notification.
   496     None if the current User is allowed to access this Notification.
   498   """
   497   """
   499   
   498   
   500   try:
   499   try:
   501     # if the current user is a developer we allow access
   500     # if the current user is a developer we allow access
   502     checkIsDeveloper(request, args, kwargs)
   501     checkIsDeveloper(kwargs)
   503     return
   502     return
   504   except out_of_band.Error:
   503   except out_of_band.Error:
   505     pass
   504     pass
   506 
   505 
   507   checkAgreesToSiteToS(request, args, kwargs)
   506   checkAgreesToSiteToS(kwargs)
   508 
       
   509   # Mine the url for params
       
   510   try:
       
   511     callback, args, kwargs = urlresolvers.resolve(request.path)
       
   512   except Exception:
       
   513     deny(request, args, kwargs)
       
   514 
   507 
   515   properties = dicts.filter(kwargs, ['link_id', 'scope_path'])
   508   properties = dicts.filter(kwargs, ['link_id', 'scope_path'])
   516 
   509 
   517   notification = notification_logic.getForFields(properties, unique=True)
   510   notification = notification_logic.getForFields(properties, unique=True)
   518   user = user_logic.getForCurrentAccount()
   511   user = user_logic.getForCurrentAccount()
   522   # if the keys are equal (which is what we want).
   515   # if the keys are equal (which is what we want).
   523   if user.key() == notification.scope.key():
   516   if user.key() == notification.scope.key():
   524     return None
   517     return None
   525 
   518 
   526   # TODO(ljvderijk) Make this give a proper error message
   519   # TODO(ljvderijk) Make this give a proper error message
   527   deny(request, args, kwargs)
   520   deny(kwargs)
   528 
   521 
   529 
   522 
   530 def checkIsMyApplication(app_logic):
   523 def checkIsMyApplication(app_logic):
   531   """Returns an alternate HTTP response if this request is for 
   524   """Returns an alternate HTTP response if this request is for 
   532      a Application belonging to the current user.
   525      a Application belonging to the current user.
   539 
   532 
   540   Returns:
   533   Returns:
   541     None if the current User is allowed to access this Application.
   534     None if the current User is allowed to access this Application.
   542   """
   535   """
   543 
   536 
   544   def wrapper(request, args, kwargs):
   537   def wrapper(kwargs):
   545     try:
   538     try:
   546       # if the current user is a developer we allow access
   539       # if the current user is a developer we allow access
   547       checkIsDeveloper(request, args, kwargs)
   540       checkIsDeveloper(kwargs)
   548       return
   541       return
   549     except out_of_band.Error:
   542     except out_of_band.Error:
   550       pass
   543       pass
   551 
   544 
   552     checkAgreesToSiteToS(request, args, kwargs)
   545     checkAgreesToSiteToS(kwargs)
   553 
   546 
   554     properties = dicts.filter(kwargs, ['link_id'])
   547     properties = dicts.filter(kwargs, ['link_id'])
   555 
   548 
   556     application = app_logic.logic.getForFields(properties, unique=True)
   549     application = app_logic.logic.getForFields(properties, unique=True)
   557     
   550     
   558     if not application:
   551     if not application:
   559       deny(request, args, kwargs)
   552       deny(kwargs)
   560     
   553     
   561     user = user_logic.getForCurrentAccount()
   554     user = user_logic.getForCurrentAccount()
   562 
   555 
   563     # We need to check to see if the key's are equal since the User
   556     # We need to check to see if the key's are equal since the User
   564     # objects are different and the default __eq__ method does not check
   557     # objects are different and the default __eq__ method does not check
   565     # if the keys are equal (which is what we want).
   558     # if the keys are equal (which is what we want).
   566     if user.key() == application.applicant.key():
   559     if user.key() == application.applicant.key():
   567       return None
   560       return None
   568 
   561 
   569     # TODO(srabbelier) Make this give a proper error message
   562     # TODO(srabbelier) Make this give a proper error message
   570     deny(request, args, kwargs)
   563     deny(kwargs)
   571 
   564 
   572   return wrapper
   565   return wrapper
   573 
   566 
   574 
   567 
   575 def checkIsMyActiveRole(role_logic):
   568 def checkIsMyActiveRole(role_logic):
   581 
   574 
   582   Returns:
   575   Returns:
   583     None if the current User has no active role for the given role_logic.
   576     None if the current User has no active role for the given role_logic.
   584   """
   577   """
   585 
   578 
   586   def wrapper(request, args, kwargs):
   579   def wrapper(kwargs):
   587     try:
   580     try:
   588       # if the current user is a developer we allow access
   581       # if the current user is a developer we allow access
   589       checkIsDeveloper(request, args, kwargs)
   582       checkIsDeveloper(kwargs)
   590       return
   583       return
   591     except out_of_band.Error:
   584     except out_of_band.Error:
   592       pass
   585       pass
   593 
   586 
   594     user = user_logic.getForCurrentAccount()
   587     user = user_logic.getForCurrentAccount()
   595 
   588 
   596     if not user or user.link_id != kwargs['link_id']:
   589     if not user or user.link_id != kwargs['link_id']:
   597       # not my role
   590       # not my role
   598       deny(request, args, kwargs)
   591       deny(kwargs)
   599 
   592 
   600     fields = {'link_id': kwargs['link_id'],
   593     fields = {'link_id': kwargs['link_id'],
   601               'scope_path': kwargs['scope_path']
   594               'scope_path': kwargs['scope_path']
   602               }
   595               }
   603 
   596 
   604     role_entity = role_logic.logic.getForFields(fields, unique=True)
   597     role_entity = role_logic.logic.getForFields(fields, unique=True)
   605 
   598 
   606     if not role_entity:
   599     if not role_entity:
   607       # no role found
   600       # no role found
   608       deny(request, args, kwargs)
   601       deny(kwargs)
   609       
   602       
   610     if role_entity.state == 'active':
   603     if role_entity.state == 'active':
   611       # this role exist and is active
   604       # this role exist and is active
   612       return
   605       return
   613     else:
   606     else:
   614       # this role is not active
   607       # this role is not active
   615       deny(request, args, kwargs)
   608       deny(kwargs)
   616 
   609 
   617   return wrapper
   610   return wrapper
   618 
   611 
   619 
   612 
   620 def checkCanInvite(request, args, kwargs):
   613 def checkCanInvite(kwargs):
   621   """Checks to see if the current user can create an invite.
   614   """Checks to see if the current user can create an invite.
   622 
   615 
   623   Note that if the current url is not in the default 'request' form
   616   Note that if the current url is not in the default 'request' form
   624   this method either deny()s or performs the wrong access check.
   617   this method either deny()s or performs the wrong access check.
   625 
   618 
   627     request: a Django HTTP request
   620     request: a Django HTTP request
   628   """
   621   """
   629 
   622 
   630   try:
   623   try:
   631     # if the current user is a developer we allow access
   624     # if the current user is a developer we allow access
   632     checkIsDeveloper(request, args, kwargs)
   625     checkIsDeveloper(kwargs)
   633     return
   626     return
   634   except out_of_band.Error:
   627   except out_of_band.Error:
   635     pass
   628     pass
   636 
       
   637   # Mine the url for params
       
   638   try:
       
   639     callback, args, kwargs = urlresolvers.resolve(request.path)
       
   640   except Exception:
       
   641     deny(request, args, kwargs)
       
   642 
   629 
   643   # Construct a new url by reshufling the kwargs
   630   # Construct a new url by reshufling the kwargs
   644   order = ['role', 'access_type', 'scope_path', 'link_id']
   631   order = ['role', 'access_type', 'scope_path', 'link_id']
   645   url_params = dicts.unzip(kwargs, order)
   632   url_params = dicts.unzip(kwargs, order)
   646   url = '/'.join([''] + list(url_params))
   633   url = '/'.join([''] + list(url_params))
   647 
   634 
   648   # Mine the reshufled url
   635   # Mine the reshufled url
   649   try:
   636   try:
   650     callback, args, kwargs = urlresolvers.resolve(url)
   637     callback, args, kwargs = urlresolvers.resolve(url)
   651   except Exception:
   638   except Exception:
   652     deny(request, args, kwargs)
   639     deny(kwargs)
   653 
   640 
   654   # Get the everything we need for the access check
   641   # Get the everything we need for the access check
   655   params = callback.im_self.getParams()
   642   params = callback.im_self.getParams()
   656   access_type = kwargs['access_type']
   643   access_type = kwargs['access_type']
   657 
   644 
   658   # Perform the access check
   645   # Perform the access check
   659   checkAccess(access_type, request, rights=params['rights'])
   646   checkAccess(access_type, rights=params['rights'], kwargs=kwargs)
   660 
   647 
   661 
   648 
   662 def checkHasPickGetArgs(request, arg, kwargs):
   649 def checkHasPickGetArgs(kwargs):
   663   """Raises an alternate HTTP response if the request misses get args.
   650   """Raises an alternate HTTP response if the request misses get args.
   664 
   651 
   665   Args:
   652   Args:
   666     request: a Django HTTP request
   653     kwargs: a dictionary with django's arguments
   667 
   654 
   668   Raises:
   655   Raises:
   669     AccessViolationResponse:
   656     AccessViolationResponse:
   670     * if continue is not in request.GET
   657     * if continue is not in request.GET
   671     * if field is not in request.GET
   658     * if field is not in request.GET
   672   """
   659   """
   673 
   660 
   674   get_args = request.GET
   661   get_args = kwargs.get('GET', {})
   675 
   662 
   676   if 'continue' in get_args and 'field' in get_args:
   663   if 'continue' in get_args and 'field' in get_args:
   677     return
   664     return
   678 
   665 
   679   #TODO(SRabbelier) inform user that return_url and field are required
   666   #TODO(SRabbelier) inform user that return_url and field are required
   680   deny(request, arg, kwargs)
   667   deny(kwargs)
   681 
   668 
   682 
   669 
   683 def checkIsDocumentPublic(request, args, kwargs):
   670 def checkIsDocumentPublic(kwargs):
   684   """Checks whether a document is public.
   671   """Checks whether a document is public.
   685 
   672 
   686   Args:
   673   Args:
   687     request: a Django HTTP request
   674     kwargs: a dictionary with django's arguments
   688   """
   675   """
   689 
   676 
   690   # TODO(srabbelier): A proper check needs to be done to see if the document
   677   # TODO(srabbelier): A proper check needs to be done to see if the document
   691   # is public or not, probably involving analysing it's scope or such.
   678   # is public or not, probably involving analysing it's scope or such.
   692   allow(request, args, kwargs)
   679   allow(kwargs)