61 |
61 |
62 DEF_LOGOUT_MSG_FMT = ugettext_lazy( |
62 DEF_LOGOUT_MSG_FMT = ugettext_lazy( |
63 'Please <a href="%(sign_out)s">sign out</a> in order to view this page') |
63 'Please <a href="%(sign_out)s">sign out</a> in order to view this page') |
64 |
64 |
65 |
65 |
66 def checkAccess(access_type, request, rights): |
66 def checkAccess(access_type, request, rights, args=None, kwargs=None): |
67 """Runs all the defined checks for the specified type. |
67 """Runs all the defined checks for the specified type. |
68 |
68 |
69 Args: |
69 Args: |
70 access_type: the type of request (such as 'list' or 'edit') |
70 access_type: the type of request (such as 'list' or 'edit') |
71 request: the Django request object |
71 request: the Django request object |
87 the response provided by the failed access check. |
87 the response provided by the failed access check. |
88 """ |
88 """ |
89 |
89 |
90 # Call each access checker |
90 # Call each access checker |
91 for check in rights['any_access']: |
91 for check in rights['any_access']: |
92 check(request) |
92 check(request, args, kwargs) |
93 |
93 |
94 if access_type not in rights: |
94 if access_type not in rights: |
95 for check in rights['unspecified']: |
95 for check in rights['unspecified']: |
96 # No checks defined, so do the 'generic' checks and bail out |
96 # No checks defined, so do the 'generic' checks and bail out |
97 check(request) |
97 check(request, args, kwargs) |
98 return |
98 return |
99 |
99 |
100 for check in rights[access_type]: |
100 for check in rights[access_type]: |
101 check(request) |
101 check(request, args, kwargs) |
102 |
102 |
103 |
103 |
104 def allow(request): |
104 def allow(request, args, kwargs): |
105 """Never returns an alternate HTTP response. |
105 """Never returns an alternate HTTP response. |
106 |
106 |
107 Args: |
107 Args: |
108 request: a Django HTTP request |
108 request: a Django HTTP request |
109 """ |
109 """ |
110 |
110 |
111 return |
111 return |
112 |
112 |
113 def deny(request): |
113 |
|
114 def deny(request, args, kwargs): |
114 """Returns an alternate HTTP response. |
115 """Returns an alternate HTTP response. |
115 |
116 |
116 Args: |
117 Args: |
117 request: a Django HTTP request |
118 request: a Django HTTP request |
118 |
119 |
182 None if User exists for a Google Account, or a subclass of |
183 None if User exists for a Google Account, or a subclass of |
183 django.http.HttpResponse which contains the alternate response |
184 django.http.HttpResponse which contains the alternate response |
184 should be returned by the calling view. |
185 should be returned by the calling view. |
185 """ |
186 """ |
186 |
187 |
187 checkIsLoggedIn(request) |
188 checkIsLoggedIn(request, args, kwargs) |
188 |
189 |
189 user = user_logic.logic.getForFields( |
190 user = user_logic.logic.getForFields( |
190 {'account': users.get_current_user()}, unique=True) |
191 {'account': users.get_current_user()}, unique=True) |
191 |
192 |
192 if user: |
193 if user: |
193 return |
194 return |
194 |
195 |
195 raise out_of_band.LoginRequest(message_fmt=DEF_NO_USER_LOGIN_MSG_FMT) |
196 raise out_of_band.LoginRequest(message_fmt=DEF_NO_USER_LOGIN_MSG_FMT) |
196 |
197 |
197 |
198 |
198 def checkIsDeveloper(request): |
199 def checkIsDeveloper(request, args, kwargs): |
199 """Returns an alternate HTTP response if Google Account is not a Developer. |
200 """Returns an alternate HTTP response if Google Account is not a Developer. |
200 |
201 |
201 Args: |
202 Args: |
202 request: a Django HTTP request |
203 request: a Django HTTP request |
203 |
204 |
208 None if Google Account is logged in and logged-in user is a Developer, |
209 None if Google Account is logged in and logged-in user is a Developer, |
209 or a subclass of django.http.HttpResponse which contains the alternate |
210 or a subclass of django.http.HttpResponse which contains the alternate |
210 response should be returned by the calling view. |
211 response should be returned by the calling view. |
211 """ |
212 """ |
212 |
213 |
213 checkIsUser(request) |
214 checkIsUser(request, args, kwargs) |
214 |
215 |
215 if accounts.isDeveloper(account=users.get_current_user()): |
216 if accounts.isDeveloper(account=users.get_current_user()): |
216 return |
217 return |
217 |
218 |
218 login_message_fmt = DEF_DEV_LOGOUT_LOGIN_MSG_FMT % { |
219 login_message_fmt = DEF_DEV_LOGOUT_LOGIN_MSG_FMT % { |
219 'role': 'a Site Developer '} |
220 'role': 'a Site Developer '} |
220 |
221 |
221 raise out_of_band.LoginRequest(message_fmt=login_message_fmt) |
222 raise out_of_band.LoginRequest(message_fmt=login_message_fmt) |
222 |
223 |
223 |
224 |
224 def checkIsHost(request): |
225 def checkIsHost(request, args, kwargs): |
225 """Returns an alternate HTTP response if Google Account has no Host entity |
226 """Returns an alternate HTTP response if Google Account has no Host entity |
226 for the specified program. |
227 for the specified program. |
227 |
228 |
228 Args: |
229 Args: |
229 request: a Django HTTP request |
230 request: a Django HTTP request |
237 should be returned by the calling view. |
238 should be returned by the calling view. |
238 """ |
239 """ |
239 |
240 |
240 try: |
241 try: |
241 # if the current user is invited to create a host profile we allow access |
242 # if the current user is invited to create a host profile we allow access |
242 checkIsInvited(request) |
243 checkIsInvited(request, args, kwargs) |
243 return |
244 return |
244 except out_of_band.Error: |
245 except out_of_band.Error: |
245 pass |
246 pass |
246 |
247 |
247 checkIsUser(request) |
248 checkIsUser(request, args, kwargs) |
248 |
249 |
249 user = user_logic.logic.getForFields( |
250 user = user_logic.logic.getForFields( |
250 {'account': users.get_current_user()}, unique=True) |
251 {'account': users.get_current_user()}, unique=True) |
251 |
252 |
252 host = host_logic.logic.getForFields( |
253 host = host_logic.logic.getForFields( |
259 'role': 'a Program Administrator '} |
260 'role': 'a Program Administrator '} |
260 |
261 |
261 raise out_of_band.LoginRequest(message_fmt=login_message_fmt) |
262 raise out_of_band.LoginRequest(message_fmt=login_message_fmt) |
262 |
263 |
263 |
264 |
264 def checkIsClubAdminForClub(request): |
265 def checkIsClubAdminForClub(request, args, kwargs): |
265 """Returns an alternate HTTP response if Google Account has no Club Admin |
266 """Returns an alternate HTTP response if Google Account has no Club Admin |
266 entity for the specified club. |
267 entity for the specified club. |
267 |
268 |
268 Args: |
269 Args: |
269 request: a Django HTTP request |
270 request: a Django HTTP request |
277 should be returned by the calling view. |
278 should be returned by the calling view. |
278 """ |
279 """ |
279 |
280 |
280 try: |
281 try: |
281 # if the current user is invited to create a host profile we allow access |
282 # if the current user is invited to create a host profile we allow access |
282 checkIsDeveloper(request) |
283 checkIsDeveloper(request, args, kwargs) |
283 return |
284 return |
284 except out_of_band.Error: |
285 except out_of_band.Error: |
285 pass |
286 pass |
286 |
287 |
287 checkIsUser(request) |
288 checkIsUser(request, args, kwargs) |
288 |
289 |
289 # TODO(srabbelier) implement this |
290 # TODO(srabbelier) implement this |
290 |
291 |
291 login_message_fmt = DEF_DEV_LOGOUT_LOGIN_MSG_FMT % { |
292 login_message_fmt = DEF_DEV_LOGOUT_LOGIN_MSG_FMT % { |
292 'role': 'a Club Admin for this Club'} |
293 'role': 'a Club Admin for this Club'} |
293 |
294 |
294 raise out_of_band.LoginRequest(message_fmt=login_message_fmt) |
295 raise out_of_band.LoginRequest(message_fmt=login_message_fmt) |
295 |
296 |
296 |
297 |
297 def checkIsInvited(request): |
298 def checkIsInvited(request, args, kwargs): |
298 """Returns an alternate HTTP response if Google Account has no Host entity |
299 """Returns an alternate HTTP response if Google Account has no Host entity |
299 for the specified program. |
300 for the specified program. |
300 |
301 |
301 Args: |
302 Args: |
302 request: a Django HTTP request |
303 request: a Django HTTP request |
310 should be returned by the calling view. |
311 should be returned by the calling view. |
311 """ |
312 """ |
312 |
313 |
313 try: |
314 try: |
314 # if the current user is a developer we allow access |
315 # if the current user is a developer we allow access |
315 checkIsDeveloper(request) |
316 checkIsDeveloper(request, args, kwargs) |
316 return |
317 return |
317 except out_of_band.Error: |
318 except out_of_band.Error: |
318 pass |
319 pass |
319 |
320 |
320 checkIsUser(request) |
321 checkIsUser(request, args, kwargs) |
321 |
322 |
322 login_message_fmt = DEF_DEV_LOGOUT_LOGIN_MSG_FMT % { |
323 login_message_fmt = DEF_DEV_LOGOUT_LOGIN_MSG_FMT % { |
323 'role': 'a Program Administrator for this Program'} |
324 'role': 'a Program Administrator for this Program'} |
324 |
325 |
325 splitpath = request.path.split('/') |
326 splitpath = request.path.split('/') |
326 splitpath = splitpath[1:] # cut off leading '' |
327 splitpath = splitpath[1:] # cut off leading '' |
327 |
328 |
328 if len(splitpath) < 4: |
329 if len(splitpath) < 4: |
329 # TODO: perhaps this needs a better explanation? |
330 # TODO: perhaps this needs a better explanation? |
330 deny(request) |
331 deny(request, args, kwargs) |
331 |
332 |
332 role = splitpath[0] |
333 role = splitpath[0] |
333 group_id = splitpath[2] |
334 group_id = splitpath[2] |
334 user_id = splitpath[3] |
335 user_id = splitpath[3] |
335 |
336 |
336 user = user_logic.logic.getForFields( |
337 user = user_logic.logic.getForFields( |
337 {'account': users.get_current_user()}, unique=True) |
338 {'account': users.get_current_user()}, unique=True) |
338 |
339 |
339 if user_id != user.link_id: |
340 if user_id != user.link_id: |
340 # TODO: perhaps this needs a better explanation? |
341 # TODO: perhaps this needs a better explanation? |
341 deny(request) |
342 deny(request, args, kwargs) |
342 |
343 |
343 properties = { |
344 properties = { |
344 'link_id': user_id, |
345 'link_id': user_id, |
345 'role': role, |
346 'role': role, |
346 'scope_path': group_id, |
347 'scope_path': group_id, |
412 None if the current User is allowed to access this Notification. |
413 None if the current User is allowed to access this Notification. |
413 """ |
414 """ |
414 |
415 |
415 try: |
416 try: |
416 # if the current user is a developer we allow access |
417 # if the current user is a developer we allow access |
417 checkIsDeveloper(request) |
418 checkIsDeveloper(request, args, kwargs) |
418 return |
419 return |
419 except out_of_band.Error: |
420 except out_of_band.Error: |
420 pass |
421 pass |
421 |
422 |
422 checkIsUser(request) |
423 checkIsUser(request, args, kwargs) |
423 |
424 |
424 # Mine the url for params |
425 # Mine the url for params |
425 try: |
426 try: |
426 callback, args, kwargs = urlresolvers.resolve(request.path) |
427 callback, args, kwargs = urlresolvers.resolve(request.path) |
427 except Exception: |
428 except Exception: |
428 deny(request) |
429 deny(request, args, kwargs) |
429 |
430 |
430 properties = dicts.filter(kwargs, ['link_id', 'scope_path']) |
431 properties = dicts.filter(kwargs, ['link_id', 'scope_path']) |
431 |
432 |
432 notification = notification_logic.logic.getForFields(properties, unique=True) |
433 notification = notification_logic.logic.getForFields(properties, unique=True) |
433 user = user_logic.logic.getForCurrentAccount() |
434 user = user_logic.logic.getForCurrentAccount() |
437 # if the keys are equal (which is what we want). |
438 # if the keys are equal (which is what we want). |
438 if user.key() == notification.scope.key(): |
439 if user.key() == notification.scope.key(): |
439 return None |
440 return None |
440 |
441 |
441 # TODO(ljvderijk) Make this give a proper error message |
442 # TODO(ljvderijk) Make this give a proper error message |
442 deny(request) |
443 deny(request, args, kwargs) |
443 |
444 |
444 def checkIsMyApplication(request): |
445 |
|
446 def checkIsMyApplication(request, args, kwargs): |
445 """Returns an alternate HTTP response if this request is for a Application belonging |
447 """Returns an alternate HTTP response if this request is for a Application belonging |
446 to the current user. |
448 to the current user. |
447 |
449 |
448 Args: |
450 Args: |
449 request: a Django HTTP request |
451 request: a Django HTTP request |
455 None if the current User is allowed to access this Application. |
457 None if the current User is allowed to access this Application. |
456 """ |
458 """ |
457 |
459 |
458 try: |
460 try: |
459 # if the current user is a developer we allow access |
461 # if the current user is a developer we allow access |
460 checkIsDeveloper(request) |
462 checkIsDeveloper(request, args, kwargs) |
461 return |
463 return |
462 except out_of_band.Error: |
464 except out_of_band.Error: |
463 pass |
465 pass |
464 |
466 |
465 checkIsUser(request) |
467 checkIsUser(request, args, kwargs) |
466 |
468 |
467 # Mine the url for params |
469 # Mine the url for params |
468 try: |
470 try: |
469 callback, args, kwargs = urlresolvers.resolve(request.path) |
471 callback, args, kwargs = urlresolvers.resolve(request.path) |
470 except Exception: |
472 except Exception: |
471 deny(request) |
473 deny(request, args, kwargs) |
472 |
474 |
473 properties = dicts.filter(kwargs, ['link_id']) |
475 properties = dicts.filter(kwargs, ['link_id']) |
474 |
476 |
475 application = group_app_logic.logic.getForFields(properties, unique=True) |
477 application = group_app_logic.logic.getForFields(properties, unique=True) |
476 user = user_logic.logic.getForCurrentAccount() |
478 user = user_logic.logic.getForCurrentAccount() |
480 # if the keys are equal (which is what we want). |
482 # if the keys are equal (which is what we want). |
481 if user.key() == application.applicant.key(): |
483 if user.key() == application.applicant.key(): |
482 return None |
484 return None |
483 |
485 |
484 # TODO(srabbelier) Make this give a proper error message |
486 # TODO(srabbelier) Make this give a proper error message |
485 deny(request) |
487 deny(request, args, kwargs) |
486 |
488 |
487 |
489 |
488 def checkCanInvite(request): |
490 def checkCanInvite(request, args, kwargs): |
489 """Checks to see if the current user can create an invite. |
491 """Checks to see if the current user can create an invite. |
490 |
492 |
491 Note that if the current url is not in the default 'request' form |
493 Note that if the current url is not in the default 'request' form |
492 this method either deny()s or performs the wrong access check. |
494 this method either deny()s or performs the wrong access check. |
493 |
495 |
495 request: a Django HTTP request |
497 request: a Django HTTP request |
496 """ |
498 """ |
497 |
499 |
498 try: |
500 try: |
499 # if the current user is a developer we allow access |
501 # if the current user is a developer we allow access |
500 checkIsDeveloper(request) |
502 checkIsDeveloper(request, args, kwargs) |
501 return |
503 return |
502 except out_of_band.Error: |
504 except out_of_band.Error: |
503 pass |
505 pass |
504 |
506 |
505 # Mine the url for params |
507 # Mine the url for params |
506 try: |
508 try: |
507 callback, args, kwargs = urlresolvers.resolve(request.path) |
509 callback, args, kwargs = urlresolvers.resolve(request.path) |
508 except Exception: |
510 except Exception: |
509 deny(request) |
511 deny(request, args, kwargs) |
510 |
512 |
511 # Construct a new url by reshufling the kwargs |
513 # Construct a new url by reshufling the kwargs |
512 order = ['role', 'access_type', 'scope_path', 'link_id'] |
514 order = ['role', 'access_type', 'scope_path', 'link_id'] |
513 url_params = dicts.unzip(kwargs, order) |
515 url_params = dicts.unzip(kwargs, order) |
514 url = '/'.join([''] + list(url_params)) |
516 url = '/'.join([''] + list(url_params)) |
515 |
517 |
516 # Mine the reshufled url |
518 # Mine the reshufled url |
517 try: |
519 try: |
518 callback, args, kwargs = urlresolvers.resolve(url) |
520 callback, args, kwargs = urlresolvers.resolve(url) |
519 except Exception: |
521 except Exception: |
520 deny(request) |
522 deny(request, args, kwargs) |
521 |
523 |
522 # Get the everything we need for the access check |
524 # Get the everything we need for the access check |
523 params = callback.im_self.getParams() |
525 params = callback.im_self.getParams() |
524 access_type = kwargs['access_type'] |
526 access_type = kwargs['access_type'] |
525 |
527 |
526 # Perform the access check |
528 # Perform the access check |
527 helper.access.checkAccess(access_type, request, rights=params['rights']) |
529 checkAccess(access_type, request, rights=params['rights']) |
528 |
530 |
529 def checkIsDocumentPublic(request): |
531 |
|
532 def checkIsDocumentPublic(request, args, kwargs): |
530 """Checks whether a document is public. |
533 """Checks whether a document is public. |
531 |
534 |
532 Args: |
535 Args: |
533 request: a Django HTTP request |
536 request: a Django HTTP request |
534 """ |
537 """ |
535 |
538 |
536 # TODO(srabbelier): A proper check needs to be done to see if the document |
539 # TODO(srabbelier): A proper check needs to be done to see if the document |
537 # is public or not, probably involving analysing it's scope or such. |
540 # is public or not, probably involving analysing it's scope or such. |
538 allow(request) |
541 allow(request, args, kwargs) |