app/soc/views/helper/access.py
changeset 1163 d8c50be19232
parent 1142 da2487767ef4
child 1176 c211191e7d81
equal deleted inserted replaced
1162:1d9396d75c13 1163:d8c50be19232
    42 from soc.logic import rights as rights_logic
    42 from soc.logic import rights as rights_logic
    43 from soc.logic.models.club_admin import logic as club_admin_logic
    43 from soc.logic.models.club_admin import logic as club_admin_logic
    44 from soc.logic.models.club_member import logic as club_member_logic
    44 from soc.logic.models.club_member import logic as club_member_logic
    45 from soc.logic.models.document import logic as document_logic
    45 from soc.logic.models.document import logic as document_logic
    46 from soc.logic.models.host import logic as host_logic
    46 from soc.logic.models.host import logic as host_logic
       
    47 from soc.logic.models.mentor import logic as mentor_logic
    47 from soc.logic.models.notification import logic as notification_logic
    48 from soc.logic.models.notification import logic as notification_logic
       
    49 from soc.logic.models.org_admin import logic as org_admin_logic
       
    50 from soc.logic.models.program import logic as program_logic
    48 from soc.logic.models.request import logic as request_logic
    51 from soc.logic.models.request import logic as request_logic
    49 from soc.logic.models.role import logic as role_logic
    52 from soc.logic.models.role import logic as role_logic
    50 from soc.logic.models.site import logic as site_logic
    53 from soc.logic.models.site import logic as site_logic
    51 from soc.logic.models.program import logic as program_logic
    54 #from soc.logic.models.student import logic as student_logic
    52 from soc.logic.models.timeline import logic as timeline_logic
    55 from soc.logic.models.timeline import logic as timeline_logic
    53 from soc.logic.models.user import logic as user_logic
    56 from soc.logic.models.user import logic as user_logic
       
    57 from soc.views.helper import redirects
    54 from soc.views import helper
    58 from soc.views import helper
    55 from soc.views import out_of_band
    59 from soc.views import out_of_band
    56 from soc.views.helper import redirects
       
    57 
    60 
    58 
    61 
    59 DEF_NO_USER_LOGIN_MSG= ugettext(
    62 DEF_NO_USER_LOGIN_MSG= ugettext(
    60   'Please create <a href="/user/create_profile">User Profile</a>'
    63   'Please create <a href="/user/create_profile">User Profile</a>'
    61   ' in order to view this page.')
    64   ' in order to view this page.')
    71   ' again as %(role)s to view this page.')
    74   ' again as %(role)s to view this page.')
    72 
    75 
    73 DEF_NEED_MEMBERSHIP_MSG_FMT = ugettext(
    76 DEF_NEED_MEMBERSHIP_MSG_FMT = ugettext(
    74   'You need to be in the %(status)s group to %(action)s'
    77   'You need to be in the %(status)s group to %(action)s'
    75   ' documents in the %(prefix)s prefix.')
    78   ' documents in the %(prefix)s prefix.')
       
    79 
       
    80 DEF_NEED_ROLE_MSG = ugettext(
       
    81   'You do not have the required role.')
       
    82 
       
    83 DEF_NOT_YOUR_ENTITY_MSG = ugettext(
       
    84   'This entity does not belong to you.')
       
    85 
       
    86 DEF_NO_ACTIVE_GROUP_MSG = ugettext(
       
    87   'There is no such active group.')
       
    88 
       
    89 DEF_NO_REQUEST_MSG = ugettext(
       
    90   'There is no accepted request that would allow you to visit this page.')
       
    91 
       
    92 DEF_NEED_PICK_ARGS_MSG = ugettext(
       
    93   'The "continue" and "field" args are not both present.')
       
    94 
       
    95 DEF_REQUEST_COMPLETED_MSG = ugettext(
       
    96   'This request cannot be accepted (it is either completed or denied).')
       
    97 
       
    98 DEF_SCOPE_INACTIVE_MSG = ugettext(
       
    99   'The scope for this request is not active.')
    76 
   100 
    77 DEF_PAGE_DENIED_MSG = ugettext(
   101 DEF_PAGE_DENIED_MSG = ugettext(
    78   'Access to this page has been restricted')
   102   'Access to this page has been restricted')
    79 
   103 
    80 DEF_LOGOUT_MSG_FMT = ugettext(
   104 DEF_LOGOUT_MSG_FMT = ugettext(
   140   rather then modifying rights directly if so desired.
   164   rather then modifying rights directly if so desired.
   141   """
   165   """
   142 
   166 
   143   MEMBERSHIP = {
   167   MEMBERSHIP = {
   144     'anyone': 'allow',
   168     'anyone': 'allow',
   145     'club_admin': 'checkIsClubAdminForScope',
   169     'club_admin': ('checkHasRole', club_admin_logic),
   146     'club_member': 'checkIsClubMemberForScope',
   170     'club_member': ('checkHasRole', club_member_logic),
   147     'host': 'checkHasHostEntity',
   171     'host': ('checkHasRole', host_logic),
   148     'org_admin': 'deny',
   172     'org_admin': ('checkHasRole', org_admin_logic),
   149     'org_mentor': 'deny',
   173     'org_mentor': ('checkHasRole', mentor_logic),
   150     'org_student': 'deny',
   174     'org_student': 'deny', #('checkHasRole', student_logic),
   151     'user': 'checkIsUser',
   175     'user': 'checkIsUser',
   152     'user_self': 'checkIsUserSelf',
   176     'user_self': ('checkIsUserSelf', 'scope_path'),
   153     }
   177     }
   154 
   178 
   155   def __init__(self, params):
   179   def __init__(self, params):
   156     """Adopts base.rights as rights if base is set.
   180     """Adopts base.rights as rights if base is set.
   157     """
   181     """
   408         'tos_link': redirects.getToSRedirect(site_logic.getSingleton())}
   432         'tos_link': redirects.getToSRedirect(site_logic.getSingleton())}
   409 
   433 
   410     raise out_of_band.LoginRequest(message_fmt=login_msg_fmt)
   434     raise out_of_band.LoginRequest(message_fmt=login_msg_fmt)
   411 
   435 
   412   @allowDeveloper
   436   @allowDeveloper
   413   def checkIsUserSelf(self, django_args):
   437   def checkIsUserSelf(self, django_args, field_name):
   414     """Checks whether the specified user is the logged in user.
   438     """Checks whether the specified user is the logged in user.
   415 
   439 
   416     Args:
   440     Args:
   417       django_args: the keyword args from django, only scope_path is used
   441       django_args: the keyword args from django, only scope_path is used
   418     """
   442     """
   419 
   443 
   420     if not 'scope_path' in django_args:
   444     if not field_name in django_args:
   421       self.deny(django_args)
   445       self.deny(django_args)
   422 
   446 
   423     if self.user.link_id == django_args['scope_path']:
   447     if self.user.link_id == django_args[field_name]:
   424       return
   448       return
   425 
   449 
   426     raise out_of_band.AccessViolation()
   450     raise out_of_band.AccessViolation()
   427 
   451 
   428   def checkIsUnusedAccount(self, django_args):
   452   def checkIsUnusedAccount(self, django_args):
   445 
   469 
   446     message_fmt = DEF_USER_ACCOUNT_INVALID_MSG_FMT % {
   470     message_fmt = DEF_USER_ACCOUNT_INVALID_MSG_FMT % {
   447         'email' : self.id.email()}
   471         'email' : self.id.email()}
   448     raise out_of_band.LoginRequest(message_fmt=message_fmt)
   472     raise out_of_band.LoginRequest(message_fmt=message_fmt)
   449 
   473 
   450 
       
   451   def checkHasUserEntity(self, django_args):
   474   def checkHasUserEntity(self, django_args):
   452     """Raises an alternate HTTP response if Google Account has no User entity.
   475     """Raises an alternate HTTP response if Google Account has no User entity.
   453 
   476 
   454     Args:
   477     Args:
   455       django_args: a dictionary with django's arguments
   478       django_args: a dictionary with django's arguments
   464 
   487 
   465     if not self.user:
   488     if not self.user:
   466       raise out_of_band.LoginRequest(message_fmt=DEF_NO_USER_LOGIN_MSG)
   489       raise out_of_band.LoginRequest(message_fmt=DEF_NO_USER_LOGIN_MSG)
   467 
   490 
   468     return
   491     return
   469 
       
   470 
   492 
   471   def checkIsDeveloper(self, django_args):
   493   def checkIsDeveloper(self, django_args):
   472     """Raises an alternate HTTP response if Google Account is not a Developer.
   494     """Raises an alternate HTTP response if Google Account is not a Developer.
   473 
   495 
   474     Args:
   496     Args:
   481       * if no Google Account is logged in at all
   503       * if no Google Account is logged in at all
   482     """
   504     """
   483 
   505 
   484     self.checkIsUser(django_args)
   506     self.checkIsUser(django_args)
   485 
   507 
   486     if accounts.isDeveloper(account=self.id):
   508     if accounts.isDeveloper(account=self.id, user=self.user):
   487       return
   509       return
   488 
   510 
   489     login_message_fmt = DEF_DEV_LOGOUT_LOGIN_MSG_FMT % {
   511     login_message_fmt = DEF_DEV_LOGOUT_LOGIN_MSG_FMT % {
   490         'role': 'a Site Developer '}
   512         'role': 'a Site Developer '}
   491 
   513 
   492     raise out_of_band.LoginRequest(message_fmt=login_message_fmt)
   514     raise out_of_band.LoginRequest(message_fmt=login_message_fmt)
   493 
   515 
   494   @allowDeveloper
   516   @allowDeveloper
   495   @denySidebar
   517   @denySidebar
   496   def checkIsGroupActive(self, django_args, group_logic):
   518   def checkIsActive(self, django_args, logic,
       
   519                     field_name='scope_path', filter_field='link_id'):
   497     """Raises an alternate HTTP response if Group status is not active.
   520     """Raises an alternate HTTP response if Group status is not active.
   498 
   521 
   499     Args:
   522     Args:
   500       django_args: a dictionary with django's arguments
   523       django_args: a dictionary with django's arguments
   501 
   524 
   503       AccessViolationResponse:
   526       AccessViolationResponse:
   504       * if no Group is found
   527       * if no Group is found
   505       * if the Group status is not active
   528       * if the Group status is not active
   506     """
   529     """
   507 
   530 
   508     fields = {'link_id': django_args['link_id']}
   531     self.checkIsUser(django_args)
   509 
   532 
   510     if django_args.get('scope_path'):
   533     if field_name and (field_name not in django_args):
   511       fields['scope_path'] = django_args['scope_path']
   534       self.deny(django_args)
   512 
   535 
   513     group_entity = group_logic.logic.getFromKeyFieldsOr404(fields)
   536     fields = {
   514 
   537         filter_field: django_args[filter_field],
   515     if group_entity.status == 'active':
   538         'status': active,
   516       return
   539         }
   517 
   540 
   518     # TODO tell the user that this group is not active
   541     if field_name:
   519     self.deny(django_args)
   542       fields['scope_path'] = django_args[field_name]
   520 
   543 
       
   544     entity = logic.geForFields(fields)
       
   545 
       
   546     if entity:
       
   547       return
       
   548 
       
   549     raise out_of_band.AccessViolation(message_fmt=DEF_NO_ACTIVE_GROUP_MSG)
       
   550 
       
   551   def checkHasRole(self, django_args, logic):
       
   552     """Checks that the user has the specified role.
       
   553     """
       
   554 
       
   555     django_args['user'] = self.user
       
   556     self.checkIsActive(django_args, logic, 'scope_path', 'user')
   521 
   557 
   522   def checkCanMakeRequestToGroup(self, django_args, group_logic):
   558   def checkCanMakeRequestToGroup(self, django_args, group_logic):
   523     """Raises an alternate HTTP response if the specified group is not in an
   559     """Raises an alternate HTTP response if the specified group is not in an
   524     active status.
   560     active status.
   525 
   561 
   535     if not group_entity:
   571     if not group_entity:
   536       raise out_of_band.Error(DEF_GROUP_NOT_FOUND_MSG, status=404)
   572       raise out_of_band.Error(DEF_GROUP_NOT_FOUND_MSG, status=404)
   537 
   573 
   538     if group_entity.status != 'active':
   574     if group_entity.status != 'active':
   539       # TODO tell the user that this group is not active
   575       # TODO tell the user that this group is not active
   540       self.deny(django_args)
   576       raise out_of_band.AccessViolation(message_fmt=DEF_NO_ACTIVE_GROUP_MSG)
   541 
   577 
   542     return
   578     return
   543 
   579 
   544   def checkCanCreateFromRequest(self, django_args, role_name):
   580   def checkCanCreateFromRequest(self, django_args, role_name):
   545     """Raises an alternate HTTP response if the specified request does not exist
   581     """Raises an alternate HTTP response if the specified request does not exist
   546        or if it's status is not group_accepted. Also when the group this request
   582        or if it's status is not group_accepted. Also when the group this request
   547        is from is in an inactive or invalid status access will be denied.
   583        is from is in an inactive or invalid status access will be denied.
   548     """
   584     """
   549 
   585 
   550     self.checkIsUser(django_args)
   586     self.checkIsUserSelf(django_args, 'link_id')
   551 
   587 
   552     user_entity = user_logic.getForCurrentAccount()
   588     fields = {
   553 
   589         'link_id': django_args['link_id'],
   554     if user_entity.link_id != django_args['link_id']:
       
   555       self.deny(django_args)
       
   556 
       
   557     fields = {'link_id': django_args['link_id'],
       
   558         'scope_path': django_args['scope_path'],
   590         'scope_path': django_args['scope_path'],
   559         'role': role_name}
   591         'role': role_name,
   560 
   592         'status': 'group_accepted',
   561     request_entity = request_logic.getFromKeyFieldsOr404(fields)
   593         }
   562 
   594 
   563     if request_entity.status != 'group_accepted':
   595     entity = request_logic.getFromFields(fields)
   564       # TODO tell the user that this request has not been accepted yet
   596 
   565       self.deny(django_args)
   597     if entity and (entity.scope.status not in ['invalid', 'inactive']):
   566 
   598       return
   567     if request_entity.scope.status in ['invalid', 'inactive']:
   599 
   568       # TODO tell the user that it is not possible to create this role anymore
   600     raise out_of_band.AccessViolation(message_fmt=DEF_CANNOT_CREATE_MSG)
   569       self.deny(django_args)
   601 
   570 
   602   def checkIsMyGroupAcceptedRequest(self, django_args):
   571     return
   603     """Checks whether the user can accept the specified request.
       
   604     """
       
   605 
       
   606     self.checkCanCreateFromRequest(django_args, django_args['role'])
   572 
   607 
   573   def checkCanProcessRequest(self, django_args, role_name):
   608   def checkCanProcessRequest(self, django_args, role_name):
   574     """Raises an alternate HTTP response if the specified request does not exist
   609     """Raises an alternate HTTP response if the specified request does not exist
   575        or if it's status is completed or denied. Also Raises an alternate HTTP response
   610        or if it's status is completed or denied. Also Raises an alternate HTTP response
   576        whenever the group in the request is not active.
   611        whenever the group in the request is not active.
   577     """
   612     """
   578 
   613 
   579     fields = {'link_id': django_args['link_id'],
   614     fields = {
       
   615         'link_id': django_args['link_id'],
   580         'scope_path': django_args['scope_path'],
   616         'scope_path': django_args['scope_path'],
   581         'role': role_name}
   617         'role': role_name,
       
   618         }
   582 
   619 
   583     request_entity = request_logic.getFromKeyFieldsOr404(fields)
   620     request_entity = request_logic.getFromKeyFieldsOr404(fields)
   584 
   621 
   585     if request_entity.status in ['completed', 'denied']:
   622     if request_entity.status in ['completed', 'denied']:
   586       # TODO tell the user that this request has been processed
   623       raise out_of_band.AccessViolation(message_fmt=DEF_REQUEST_COMPLETED_MSG)
   587       self.deny(django_args)
   624 
   588 
   625     if request_entity.scope.status == 'active':
   589     if request_entity.scope.status != 'active':
   626       return
   590       # TODO tell the user that this group cannot process requests
   627 
   591       self.deny(django_args)
   628     raise out_of_band.AccessViolation(message_fmt=DEF_SCOPE_INACTIVE_MSG)
   592 
       
   593     return
       
   594 
       
   595   def checkIsMyGroupAcceptedRequest(self, django_args):
       
   596     """Raises an alternate HTTP response if the specified request does not exist
       
   597        or if it's status is not group_accepted.
       
   598     """
       
   599 
       
   600     self.checkIsUser(django_args)
       
   601 
       
   602     user_entity = user_logic.getForCurrentAccount()
       
   603 
       
   604     if user_entity.link_id != django_args['link_id']:
       
   605       # not the current user's request
       
   606       self.deny(django_args)
       
   607 
       
   608     fields = {'link_id': django_args['link_id'],
       
   609               'scope_path': django_args['scope_path'],
       
   610               'role': django_args['role']}
       
   611 
       
   612     request_entity = request_logic.getForFields(fields, unique=True)
       
   613 
       
   614     if not request_entity:
       
   615       # TODO return 404
       
   616       self.deny(django_args)
       
   617 
       
   618     if request_entity.status != 'group_accepted':
       
   619       self.deny(django_args)
       
   620 
       
   621     return
       
   622 
       
   623   @allowDeveloper
       
   624   @denySidebar
       
   625   def checkIsHost(self, django_args):
       
   626     """Raises an alternate HTTP response if Google Account has no Host entity.
       
   627 
       
   628     Args:
       
   629       request: a Django HTTP request
       
   630 
       
   631     Raises:
       
   632       AccessViolationResponse:
       
   633       * if User is not already a Host, or
       
   634       * if User has not agreed to the site-wide ToS, or
       
   635       * if no User exists for the logged-in Google Account, or
       
   636       * if the user is not even logged in
       
   637     """
       
   638 
       
   639     self.checkIsUser(django_args)
       
   640 
       
   641     scope_path = None
       
   642 
       
   643     if 'scope_path' in django_args:
       
   644       scope_path = django_args['scope_path']
       
   645     if 'link_id' in django_args:
       
   646       scope_path = django_args['link_id']
       
   647 
       
   648     fields = {'user': self.user,
       
   649               'status': 'active'}
       
   650 
       
   651     if scope_path:
       
   652       fields['scope_path'] = scope_path
       
   653 
       
   654     host = host_logic.getForFields(fields, unique=True)
       
   655 
       
   656     if host:
       
   657       return
       
   658 
       
   659     login_message_fmt = DEF_DEV_LOGOUT_LOGIN_MSG_FMT % {
       
   660         'role': 'a Program Administrator '}
       
   661 
       
   662     raise out_of_band.LoginRequest(message_fmt=login_message_fmt)
       
   663 
       
   664   def checkHasHostEntity(self, django_args):
       
   665     """Checks whether the current user has a Host entity.
       
   666     """
       
   667 
       
   668     self.checkIsHost({})
       
   669 
   629 
   670   @denySidebar
   630   @denySidebar
   671   @allowDeveloper
   631   @allowDeveloper
   672   def checkIsHostForProgram(self, django_args):
   632   def checkIsHostForProgram(self, django_args):
   673     """Checks if the user is a host for the specified program.
   633     """Checks if the user is a host for the specified program.
   678 
   638 
   679     if not program or program.status == 'invalid':
   639     if not program or program.status == 'invalid':
   680       self.deny(django_args)
   640       self.deny(django_args)
   681 
   641 
   682     new_args = {'scope_path': program.scope_path }
   642     new_args = {'scope_path': program.scope_path }
   683     self.checkIsHost(new_args)
   643     self.checkHasRole(new_args, host_logic)
   684 
       
   685   @allowDeveloper
       
   686   def checkIsHostForSponsor(self, django_args):
       
   687     """Raises an alternate HTTP response if Google Account has no Host entity
       
   688        for the specified Sponsor.
       
   689 
       
   690     Args:
       
   691       request: a Django HTTP request
       
   692 
       
   693     Raises:
       
   694       AccessViolationResponse:
       
   695       * if User is not already a Host for the specified program, or
       
   696       * if User has not agreed to the site-wide ToS, or
       
   697       * if no User exists for the logged-in Google Account, or
       
   698       * if the user is not even logged in
       
   699     """
       
   700 
       
   701     self.checkIsUser(django_args)
       
   702 
       
   703     user = user_logic.getForCurrentAccount()
       
   704 
       
   705     if django_args.get('scope_path'):
       
   706       scope_path = django_args['scope_path']
       
   707     else:
       
   708       scope_path = django_args['link_id']
       
   709 
       
   710     fields = {'user': user,
       
   711               'scope_path': scope_path,
       
   712               'status': 'active'}
       
   713 
       
   714     host = host_logic.getForFields(fields, unique=True)
       
   715 
       
   716     if host:
       
   717       return
       
   718 
       
   719     login_message_fmt = DEF_DEV_LOGOUT_LOGIN_MSG_FMT % {
       
   720         'role': 'a Program Administrator '}
       
   721 
       
   722     raise out_of_band.LoginRequest(message_fmt=login_message_fmt)
       
   723 
       
   724   @allowDeveloper
       
   725   def checkIsClubAdminForClub(self, django_args):
       
   726     """Returns an alternate HTTP response if Google Account has no Club Admin
       
   727        entity for the specified club.
       
   728 
       
   729     Args:
       
   730       django_args: a dictionary with django's arguments
       
   731 
       
   732      Raises:
       
   733        AccessViolationResponse: if the required authorization is not met
       
   734 
       
   735     Returns:
       
   736       None if Club Admin exists for the specified club, or a subclass of
       
   737       django.http.HttpResponse which contains the alternate response
       
   738       should be returned by the calling view.
       
   739     """
       
   740 
       
   741     self.checkIsUser(django_args)
       
   742 
       
   743     user = user_logic.getForCurrentAccount()
       
   744 
       
   745     if django_args.get('scope_path'):
       
   746       scope_path = django_args['scope_path']
       
   747     else:
       
   748       scope_path = django_args['link_id']
       
   749 
       
   750     fields = {'user': user,
       
   751               'scope_path': scope_path,
       
   752               'status': 'active'}
       
   753 
       
   754     club_admin_entity = club_admin_logic.getForFields(fields, unique=True)
       
   755 
       
   756     if club_admin_entity:
       
   757       return
       
   758 
       
   759     login_message_fmt = DEF_DEV_LOGOUT_LOGIN_MSG_FMT % {
       
   760         'role': 'a Club Admin for this Club'}
       
   761 
       
   762     raise out_of_band.LoginRequest(message_fmt=login_message_fmt)
       
   763 
       
   764   @allowDeveloper
       
   765   @allowIfCheckPasses('checkIsClubAdminForClub')
       
   766   def checkIsClubMemberForClub(self, django_args):
       
   767     """Returns an alternate HTTP response if Google Account has no Club Member
       
   768        entity for the specified club.
       
   769 
       
   770     Args:
       
   771       django_args: a dictionary with django's arguments
       
   772 
       
   773      Raises:
       
   774        AccessViolationResponse: if the required authorization is not met
       
   775 
       
   776     Returns:
       
   777       None if Club Member exists for the specified club, or a subclass of
       
   778       django.http.HttpResponse which contains the alternate response
       
   779       should be returned by the calling view.
       
   780     """
       
   781 
       
   782     self.checkIsUser(django_args)
       
   783 
       
   784     if django_args.get('scope_path'):
       
   785       scope_path = django_args['scope_path']
       
   786     else:
       
   787       scope_path = django_args['link_id']
       
   788 
       
   789     fields = {'user': self.user,
       
   790               'scope_path': scope_path,
       
   791               'status': 'active'}
       
   792 
       
   793     club_member_entity = club_member_logic.getForFields(fields, unique=True)
       
   794 
       
   795     if club_member_entity:
       
   796       return
       
   797 
       
   798     login_message_fmt = DEF_DEV_LOGOUT_LOGIN_MSG_FMT % {
       
   799         'role': 'a Club Member for this Club'}
       
   800 
       
   801     raise out_of_band.LoginRequest(message_fmt=login_message_fmt)
       
   802 
       
   803   def checkIsClubAdminForScope(self, django_args):
       
   804     """Checks whether the current user is a Club Mdmin.
       
   805 
       
   806     Args:
       
   807       django_args: the keyword arguments from django, only scope_path is used
       
   808     """
       
   809 
       
   810     scope_path = django_args['scope_path']
       
   811     self.checkIsClubAdminForClub({'link_id': scope_path})
       
   812 
       
   813   def checkIsClubMemberForScope(self, django_args):
       
   814     """Checks whether the current user is a Club Mdmin.
       
   815 
       
   816     Args:
       
   817       django_args: the keyword arguments from django, only scope_path is used
       
   818     """
       
   819 
       
   820     scope_path = django_args['scope_path']
       
   821     self.checkIsClubMemberForClub({'link_id': scope_path})
       
   822 
   644 
   823   @allowDeveloper
   645   @allowDeveloper
   824   def checkIsApplicationAccepted(self, django_args, app_logic):
   646   def checkIsApplicationAccepted(self, django_args, app_logic):
   825     """Returns an alternate HTTP response if Google Account has no Club App
   647     """Returns an alternate HTTP response if Google Account has no Club App
   826        entity for the specified Club.
   648        entity for the specified Club.
   837       should be returned by the calling view.
   659       should be returned by the calling view.
   838     """
   660     """
   839 
   661 
   840     self.checkIsUser(django_args)
   662     self.checkIsUser(django_args)
   841 
   663 
   842     user = user_logic.getForCurrentAccount()
       
   843 
       
   844     properties = {
   664     properties = {
   845         'applicant': user,
   665         'applicant': self.user,
   846         'status': 'accepted'
   666         'status': 'accepted'
   847         }
   667         }
   848 
   668 
   849     application = app_logic.logic.getForFields(properties, unique=True)
   669     application = app_logic.getForFields(properties, unique=True)
   850 
   670 
   851     if application:
   671     if application:
   852       return
   672       return
   853 
   673 
   854     # TODO(srabbelier) Make this give a proper error message
   674     # TODO(srabbelier) Make this give a proper error message
   855     self.deny(django_args)
   675     self.deny(django_args)
   856 
   676 
   857   @allowDeveloper
   677   def checkIsMyEntity(self, django_args, logic, field_name='user'):
   858   def checkIsMyNotification(self, django_args):
   678     """Checks whether the entity belongs to the user.
   859     """Returns an alternate HTTP response if this request is for
       
   860        a Notification belonging to the current user.
       
   861 
       
   862     Args:
       
   863       django_args: a dictionary with django's arguments
       
   864 
       
   865      Raises:
       
   866        AccessViolationResponse: if the required authorization is not met
       
   867 
       
   868     Returns:
       
   869       None if the current User is allowed to access this Notification.
       
   870     """
   679     """
   871 
   680 
   872     self.checkIsUser(django_args)
   681     self.checkIsUser(django_args)
   873 
   682 
   874     properties = dicts.filter(django_args, ['link_id', 'scope_path'])
   683     fields = {
   875 
   684         'link_id': django_args['link_id'],
   876     notification = notification_logic.getForFields(properties, unique=True)
   685         field_name: self.user,
   877     user = user_logic.getForCurrentAccount()
   686         }
   878 
   687 
   879     # We need to check to see if the key's are equal since the User
   688     entity = logic.getForFields(fields)
   880     # objects are different and the default __eq__ method does not check
   689 
   881     # if the keys are equal (which is what we want).
   690     if entity:
   882     if user.key() == notification.scope.key():
   691       return
   883       return None
   692 
   884 
   693     raise out_of_band.AccessViolation(message_fmt=DEF_NOT_YOUR_ENTITY_MSG)
   885     # TODO(ljvderijk) Make this give a proper error message
       
   886     self.deny(django_args)
       
   887 
       
   888   @allowDeveloper
       
   889   def checkIsMyApplication(self, django_args, app_logic):
       
   890     """Returns an alternate HTTP response if this request is for
       
   891        a Application belonging to the current user.
       
   892 
       
   893     Args:
       
   894       request: a Django HTTP request
       
   895 
       
   896      Raises:
       
   897        AccessViolationResponse: if the required authorization is not met
       
   898 
       
   899     Returns:
       
   900       None if the current User is allowed to access this Application.
       
   901     """
       
   902 
       
   903     self.checkIsUser(django_args)
       
   904 
       
   905     properties = dicts.filter(django_args, ['link_id'])
       
   906 
       
   907     application = app_logic.logic.getForFields(properties, unique=True)
       
   908 
       
   909     if not application:
       
   910       self.deny(django_args)
       
   911 
       
   912     # We need to check to see if the key's are equal since the User
       
   913     # objects are different and the default __eq__ method does not check
       
   914     # if the keys are equal (which is what we want).
       
   915     if self.user.key() == application.applicant.key():
       
   916       return None
       
   917 
       
   918     # TODO(srabbelier) Make this give a proper error message
       
   919     self.deny(django_args)
       
   920 
       
   921   @allowDeveloper
       
   922   def checkIsMyActiveRole(self, django_args, role_logic):
       
   923     """Returns an alternate HTTP response if there is no active role found for
       
   924        the current user using the given role_logic.
       
   925 
       
   926      Raises:
       
   927        AccessViolationResponse: if the required authorization is not met
       
   928 
       
   929     Returns:
       
   930       None if the current User has an active role for the given role_logic.
       
   931     """
       
   932 
       
   933     if not self.user or self.user.link_id != django_args['link_id']:
       
   934       # not my role
       
   935       self.deny(django_args)
       
   936 
       
   937     fields = {'link_id': django_args['link_id'],
       
   938               'scope_path': django_args['scope_path'],
       
   939               }
       
   940 
       
   941     role_entity = role_logic.logic.getFromKeyFieldsOr404(fields)
       
   942 
       
   943     if role_entity.status != 'active':
       
   944       # role is not active
       
   945       self.deny(django_args)
       
   946 
       
   947 
   694 
   948   @allowDeveloper
   695   @allowDeveloper
   949   @denySidebar
   696   @denySidebar
   950   def checkIsAllowedToManageRole(self, django_args, role_logic, manage_role_logic):
   697   def checkIsAllowedToManageRole(self, django_args, role_logic, manage_role_logic):
   951     """Returns an alternate HTTP response if the user is not allowed to manage
   698     """Returns an alternate HTTP response if the user is not allowed to manage
   965            that belongs to the same scope as the role that needs to be managed
   712            that belongs to the same scope as the role that needs to be managed
   966     """
   713     """
   967 
   714 
   968     try:
   715     try:
   969       # check if it is my role the user's own role
   716       # check if it is my role the user's own role
   970       self.checkIsMyActiveRole(django_args, role_logic)
   717       self.checkHasRole(django_args, role_logic)
   971     except out_of_band.Error:
   718     except out_of_band.Error:
   972       pass
   719       pass
   973 
   720 
   974     # apparently it's not the user's role so check if managing this role is allowed
   721     # apparently it's not the user's role so check if managing this role is allowed
   975     fields = {'link_id': django_args['link_id'],
   722     fields = {
   976               'scope_path': django_args['scope_path'],
   723         'link_id': django_args['link_id'],
   977               }
   724         'scope_path': django_args['scope_path'],
   978 
   725         'status': 'active',
   979     role_entity = role_logic.logic.getFromKeyFieldsOr404(fields)
   726         }
   980 
   727 
   981     if role_entity.status != 'active':
   728     role_entity = role_logic.logic.getForFields(fields)
   982       # cannot manage this entity
   729 
   983       self.deny(django_args)
   730     fields = {
   984 
   731         'link_id': self.user.link_id,
   985     fields = {'link_id': self.user.link_id,
       
   986         'scope_path': django_args['scope_path'],
   732         'scope_path': django_args['scope_path'],
   987         'status': 'active'
   733         'status': 'active'
   988         }
   734         }
   989 
   735 
   990     manage_entity = manage_role_logic.logic.getForFields(fields, unique=True)
   736     manage_entity = manage_role_logic.logic.getForFields(fields, unique=True)
  1009     get_args = django_args.get('GET', {})
   755     get_args = django_args.get('GET', {})
  1010 
   756 
  1011     if 'continue' in get_args and 'field' in get_args:
   757     if 'continue' in get_args and 'field' in get_args:
  1012       return
   758       return
  1013 
   759 
  1014     #TODO(SRabbelier) inform user that return_url and field are required
   760     raise out_of_band.Error(message_fmt=DEF_NEED_PICK_ARGS_MSG)
  1015     self.deny(django_args)
       
  1016 
   761 
  1017   @denySidebar
   762   @denySidebar
  1018   @allowDeveloper
   763   @allowDeveloper
  1019   def checkIsDocumentReadable(self, django_args):
   764   def checkIsDocumentReadable(self, django_args):
  1020     """Checks whether a document is readable.
   765     """Checks whether a document is readable.
  1042     document = document_logic.getFromKeyFields(key_fields)
   787     document = document_logic.getFromKeyFields(key_fields)
  1043 
   788 
  1044     self.checkMembership('write', document.prefix,
   789     self.checkMembership('write', document.prefix,
  1045                          document.write_access, django_args)
   790                          document.write_access, django_args)
  1046 
   791 
  1047   @allowIfCheckPasses('checkIsHostForProgram')
       
  1048   def checkIsProgramVisible(self, django_args):
       
  1049     """Checks whether a program is visible.
       
  1050     """
       
  1051 
       
  1052     if 'entity' in django_args:
       
  1053       program = django_args['entity']
       
  1054     else:
       
  1055       key_fields = program_logic.getKeyFieldsFromFields(django_args)
       
  1056       program = program_logic.getFromKeyFields(key_fields)
       
  1057 
       
  1058     if not program:
       
  1059       self.deny(django_args)
       
  1060 
       
  1061     if program.status == 'visible':
       
  1062       return
       
  1063 
       
  1064     context = django_args.get('context', {})
       
  1065     context['title'] = 'Access denied'
       
  1066 
       
  1067     message_fmt = DEF_DEV_LOGOUT_LOGIN_MSG_FMT % {
       
  1068         'role': ugettext('a Program Administrator')}
       
  1069 
       
  1070     raise out_of_band.AccessViolation(DEF_DEV_LOGOUT_LOGIN_MSG_FMT,
       
  1071                                       context=context)
       
  1072 
       
  1073   def checkCanEditTimeline(self, django_args):
   792   def checkCanEditTimeline(self, django_args):
  1074     """Checks whether this program's timeline may be edited.
   793     """Checks whether this program's timeline may be edited.
  1075     """
   794     """
  1076 
   795 
  1077     time_line_keyname = django_args['scope_path']
   796     time_line_keyname = django_args['scope_path']
  1081       # timeline does not exists so deny
   800       # timeline does not exists so deny
  1082       self.deny(django_args)
   801       self.deny(django_args)
  1083 
   802 
  1084     split_keyname = time_line_keyname.rsplit('/')
   803     split_keyname = time_line_keyname.rsplit('/')
  1085 
   804 
  1086     fields = {'scope_path' : split_keyname[0],
   805     fields = {
       
   806         'scope_path' : split_keyname[0],
  1087         'link_id' : split_keyname[1],
   807         'link_id' : split_keyname[1],
  1088         }
   808         }
  1089 
   809 
  1090     return self.checkIsHostForProgram(fields)
   810     self.checkIsHostForProgram(fields)