def checkRoleAndStatusForTask(self, django_args, allowed_roles, role_status, task_status): """Checks if the current user has access to the given task. This method checks if the current user is in one of the allowed_roles and has specified role_status, If yes, allows him to access the Task page. Args: django_args: a dictionary with django's arguments allowed_roles: list with names for the roles allowed to pass access check role_status: list with states allowed for the role task_status: a list with states allowed for the task Raises: AccessViolationResponse: - If there is no task found - If the task is not in one of the required states. - If the user does not have any of the required roles """ self.checkIsUser(django_args) if 'link_id' in django_args: # bail out with 404 if no task is found task_entity = gci_task_logic.logic.getFromKeyFieldsOr404( django_args) if not task_entity.status in task_status: # this task can not be accessed at the moment raise out_of_band.AccessViolation( message_fmt=DEF_NO_ACTIVE_ENTITY_MSG) user_entity = self.user filter = { 'user': user_entity, 'scope_path': django_args['scope_path'], 'status': role_status } if 'host' in allowed_roles: # check if the current user is a host for this proposal's program if host_logic.logic.getForFields(filter, unique=True): return if 'gci/org_admin' in allowed_roles: # check if the current user is an admin for this task's org if gci_org_admin_logic.logic.getForFields(filter, unique=True): return if 'gci/mentor' in allowed_roles: # check if the current user is a mentor for this task's org if gci_mentor_logic.logic.getForFields(filter, unique=True): return if 'public' in allowed_roles: return # no roles found, access denied raise out_of_band.AccessViolation(message_fmt=DEF_NEED_ROLE_MSG)
def checkCanEditStudentProjectAsStudent(self, django_args): """Checks whether the project can be edited in a student mode by the current user. Args: django_args: a dictionary with django's arguments Raises: AccessViolationResponse: - If there is no project found - If the project does not belong to the current user """ self.checkIsUser() project_entity = student_project_logic.getFromKeyFieldsOr404( django_args) student_entity = project_entity.student if student_entity.user.key() != self.user.key(): raise out_of_band.AccessViolation( message_fmt=access.DEF_NOT_YOUR_ENTITY_MSG) if student_entity.status != 'active': raise out_of_band.AccessViolation( message_fmt=access.DEF_NO_ACTIVE_ENTITY_MSG) return
def checkCanDownloadConsentForms(self, django_args, student_logic, forms_data): """Checks if the user is a student who can download the forms i.e. the blobs he has requested. Args: django_args: a dictionary with django's arguments student_logic: student logic used to look up student entity forms_data: dictionary containing the data related to the forms that student should upload and entities that store the form. Raises: AccessViolationResponse: - If there are no forms uploaded for the student. - If the logged in user is not the one to whom the form belongs to. """ self.checkIsUser(django_args) user_entity = self.user try: # if the current user is the program host no more access is required if self.checkIsHostForProgramInScope(django_args, gci_program_logic.logic): return except out_of_band.AccessViolation: # if the user is not the host proceed for other checks # NOTE: This is not combined with the following exception because # if we catch AccessViolation there the access check for blob key # being null which raises the same exception will also be caught pass filter = { 'user': user_entity, 'status': 'active', 'scope_path': django_args['scope_path'], 'link_id': django_args['link_id'], } student_entity = student_logic.getForFields(filter, unique=True) try: form_type = django_args['GET'].get('type', '') blob_key = django_args['GET'].get('key', '') if not blob_key: raise out_of_band.AccessViolation( message_fmt=DEF_NO_FILE_SPECIFIED_MSG) form_entity_name = forms_data.get(form_type, '') form_entity = getattr(student_entity, form_entity_name) if blob_key == str(form_entity.key()): return except AttributeError: pass raise out_of_band.AccessViolation(message_fmt=DEF_NO_FILE_ACCESS_MSG)
def checkStatusForTask(self, django_args): """Checks if the current user has access to the given task. This method checks if the current user is either an GCI Org Admin or a Mentor and is active, if yes it allows them to view the task page at any task state. If the user is none of the above, it checks the status of the task, and if it is in one of the valid published states it allows access to view the task page. Args: django_args: a dictionary with django's arguments Raises: AccessViolationResponse: - If there is no task found - If the task is not in one of the required states. """ user_entity = self.user # bail out with 404 if no task is found task_entity = gci_task_logic.logic.getFromKeyFieldsOr404(django_args) if (user_entity and task_entity.user and task_entity.user.key() == user_entity.key()): return filter = { 'user': user_entity, 'status': 'active', } if host_logic.logic.getForFields(filter, unique=True): return filter['scope_path'] = django_args['scope_path'] if gci_org_admin_logic.logic.getForFields(filter, unique=True): return if gci_mentor_logic.logic.getForFields(filter, unique=True): return org_entity = gci_org_logic.logic.getFromKeyNameOr404( django_args['scope_path']) if not timeline_helper.isAfterEvent(org_entity.scope.timeline, 'tasks_publicly_visible'): raise out_of_band.AccessViolation( message_fmt=DEF_PAGE_INACTIVE_MSG) if task_entity.status in ['Unapproved', 'Unpublished', 'Invalid']: # this proposal can not be task at the moment raise out_of_band.AccessViolation(message_fmt=DEF_NO_PUB_TASK_MSG)
def checkIsStudentProposalPubliclyVisible(self, django_args): """Checks whether the proposal's content can be seen by everyone. Args: django_args: a dictionary with django's arguments Raises: AccessViolationResponse: - If there is no proposal found - If the proposal cannot be publicly seen """ proposal_entity = student_proposal_logic.getFromKeyFieldsOr404( django_args) user = self.user proposal_owner = proposal_entity.scope.user.key().id_or_name() # student may see his own proposal even if public view is not available if user and user.key().id_or_name() == proposal_owner: return if not proposal_entity.is_publicly_visible: raise out_of_band.AccessViolation( message_fmt=DEF_PROPOSAL_NOT_PUBLIC) return
def checkCanApply(self, django_args): """Checks if the user has the completed at least one task to register as a student. Args: django_args: a dictionary with django's arguments Raises: AccessViolationResponse: - If student has not completed even a single task """ self.checkIsUser(django_args) program_entity = gci_program_logic.logic.getFromKeyNameOr404( django_args['scope_path']) filter = { 'user': self.user, 'program': program_entity, 'status': 'AwaitingRegistration', } if gci_task_logic.logic.getForFields(filter, unique=True): return # no completed tasks found, access denied raise out_of_band.AccessViolation(message_fmt=DEF_CANT_REGISTER)
def checkIsStudent(self, django_args, key_location, status): """Checks if the current user is the given student. Args: django_args: a dictionary with django's arguments key_location: the key for django_args in which the key_name from the student is stored status: the allowed status for the student """ self.checkIsUser(django_args) if 'seed' in django_args: key_name = django_args['seed'][key_location] else: key_name = django_args[key_location] student_entity = student_logic.getFromKeyName(key_name) if not student_entity or student_entity.status not in status: raise out_of_band.AccessViolation( message_fmt=DEF_SIGN_UP_AS_STUDENT_MSG) if student_entity.user.key() != self.user.key(): # this is not the page for the current user self.deny(django_args) return
def checkCanOpenTaskList(self, django_args): """Checks if the current user is allowed to see a list of his tasks. Args: django_args: a dictionary with django's arguments Raises: AccessViolationResponse: - if the user is not registered as a student; and - if the user has not claimed a single task """ self.checkIsUser(django_args) try: return self.checkHasRoleForScope(django_args, ghop_student_logic) except out_of_band.Error: pass program = ghop_program_logic.logic.getFromKeyNameOr404( django_args['scope_path']) filter = { 'user': self.user, 'program': program, } if not ghop_task_logic.logic.getForFields(filter, unique=True): raise out_of_band.AccessViolation( message_fmt=DEF_NO_TASKS_ASSIGNED)
def checkCanStudentPropose(self, django_args, key_location, check_limit): """Checks if the program for this student accepts proposals. Args: django_args: a dictionary with django's arguments key_location: the key for django_args in which the key_name from the student is stored check_limit: iff true checks if the student reached the apps_tasks_limit for the given program. """ from soc.logic.helper import timeline as timeline_helper self.checkIsUser(django_args) if django_args.get('seed'): key_name = django_args['seed'][key_location] else: key_name = django_args[key_location] student_entity = student_logic.getFromKeyName(key_name) if not student_entity or student_entity.status == 'invalid': raise out_of_band.AccessViolation( message_fmt=DEF_SIGN_UP_AS_STUDENT_MSG) program_entity = student_entity.scope if not timeline_helper.isActivePeriod(program_entity.timeline, 'student_signup'): raise out_of_band.AccessViolation( message_fmt=access.DEF_PAGE_INACTIVE_MSG) if check_limit: # count all studentproposals by the student fields = {'scope': student_entity} proposal_query = student_proposal_logic.getQueryForFields(fields) if proposal_query.count() >= program_entity.apps_tasks_limit: # too many proposals access denied raise out_of_band.AccessViolation( message_fmt=DEF_MAX_PROPOSALS_REACHED) return
def checkOrgHasNoOpenTasks(self, django_args): """Checks if the organization does not have any tasks which might be claimed by students. """ org_entity = gci_org_logic.logic.getFromKeyFieldsOr404(django_args) fields = {'status': ['Open', 'Reopened'], 'scope': org_entity} if gci_task_logic.logic.getForFields(fields, unique=True): raise out_of_band.AccessViolation(message_fmt=DEF_ORG_HAS_TASKS)
def checkIsNotStudentForProgramOfOrg(self, django_args, org_logic, student_logic): """Extends the basic with one that checks whether the current user has claimed a task in the program. Args: See Checker.checkIsNotStudentForProgramOfOrg(). """ org_entity = super(GCIChecker, self).checkIsNotStudentForProgramOfOrg( django_args, org_logic, student_logic) fields = {'user': self.user, 'program': org_entity.scope} if gci_task_logic.logic.getForFields(fields, unique=True): raise out_of_band.AccessViolation( message_fmt=DEF_ALREADY_CLAIMED_A_TASK) return org_entity
def checkCanOpenTaskList(self, django_args, role_logic, role): """Checks if the current user is allowed to see a list of his tasks. Args: django_args: a dictionary with django's arguments role_logic: the specific role whose logic must be used to check for the scope role: name of the role for this check is performed Raises: AccessViolationResponse: - if the user is not registered as a student; and - if the user has not claimed a single task """ self.checkIsUser(django_args) try: return self.checkHasRoleForScope(django_args, role_logic) except out_of_band.Error: pass program = gci_program_logic.logic.getFromKeyNameOr404( django_args['scope_path']) filter = { 'program': program, } if role == 'gci/student': filter['user'] = self.user elif role == 'gci/mentor': mentor_filter = { 'user': self.user, 'program': program, 'status': 'active' } mentor_entity = role_logic.getForFields(mentor_filter, unique=True) filter['mentors'] = [mentor_entity] if not gci_task_logic.logic.getForFields(filter, unique=True): raise out_of_band.AccessViolation( message_fmt=DEF_NO_TASKS_AFFILIATED)
def checkStudentProjectHasStatus(self, django_args, allowed_status): """Checks whether the Project has one of the given statuses. Args: django_args: a dictionary with django's arguments allowed_status: list with the allowed statuses for the entity Raises: AccessViolationResponse: - If there is no project found - If the project is not in the requested status """ project_entity = student_project_logic.getFromKeyFieldsOr404( django_args) if not project_entity.status in allowed_status: raise out_of_band.AccessViolation( message_fmt=access.DEF_NO_ACTIVE_ENTITY_MSG) return
def checkTimelineFromTaskScope(self, django_args, status, period_name): """Checks the timeline for the program found in the scope variable of a Task. Args: django_args: a dictionary with django's arguments status: one of three strings, during which calls isActivePeriod(), before which calls isBeforeEvent() and after which calls isAfterEvent(). period_name: the name of the period to check the timeline for. Raises: AccessViolationResponse: - if the program is not in a valid state - if the period specified does not pass the required status check """ org_entity = gci_org_logic.logic.getFromKeyNameOr404( django_args['scope_path']) program_args = {'scope_path': org_entity.scope_path} if status is 'during': return self.checkIsActivePeriod(program_args, period_name, 'scope_path', gci_program_logic.logic) elif status is 'before': return self.checkIsBeforeEvent(program_args, period_name, 'scope_path', gci_program_logic.logic) elif status is 'after': return self.checkIsAfterEvent(program_args, period_name, 'scope_path', gci_program_logic.logic) # no right status set, but we can't give the user access raise out_of_band.AccessViolation(message_fmt=DEF_UNEXPECTED_ERROR)
def checkIsAllowedToViewProjectSurveyRecordAs(self, django_args, survey_logic, role_name, record_key_location): """Checks whether the current user is allowed to view the record given in the GET data by the record_key_location. Args: django_args: a dictionary with django's arguments survey_logic: Survey Logic instance that belongs to the SurveyRecord type in question role_name: string containing either "student" or "mentor". Determines which of the roles the within the project the current user should have to view the evaluation results. record_key_location: string containing the name of the GET param which contains the id for the SurveyRecord to retrieve Raises: AccessViolation if: - No valid numeric Record ID is given in the POST data. - No Record could be retrieved for the given Record ID. - The current user has not taken the survey, is not the Student/Mentor (depending on the role_name) and is not an Org Admin for the project to which the SurveyRecord belongs. """ if not role_name in ['mentor', 'student']: raise InvalidArgumentError('role_name is not mentor or student') self.checkIsUser(django_args) user_entity = self.user get_dict = django_args['GET'] record_id = get_dict.get(record_key_location) if not record_id or not record_id.isdigit(): raise out_of_band.AccessViolation( message_fmt=access.DEF_NO_VALID_RECORD_ID) else: record_id = int(record_id) record_logic = survey_logic.getRecordLogic() record_entity = record_logic.getFromIDOr404(record_id) if record_entity.user.key() == user_entity.key(): # this record belongs to the current user return if role_name == 'student': role_entity = record_entity.project.student elif role_name == 'mentor': role_entity = record_entity.project.mentor if role_entity.user.key() == user_entity.key() and ( role_entity.status in ['active', 'inactive']): # this user has the role required return fields = { 'user': user_entity, 'scope': record_entity.org, 'status': ['active', 'inactive'] } admin_entity = org_admin_logic.getForFields(fields, unique=True) if admin_entity: # this user is org admin for the retrieved record's project return # The current user is no Org Admin, has not taken the Survey and is not # the one responsible for taking this survey. raise out_of_band.AccessViolation( message_fmt=access.DEF_NOT_YOUR_RECORD)
def checkIsAllowedToTakeProjectSurveyAs(self, django_args, survey_logic, role_name, project_key_location): """Checks whether a ProjectSurvey can be taken by the current User. role_name argument determines wether the current user is taking the survey as a student or mentor specified by the project in GET dict. If the survey is taken as a mentor, org admins for the Organization in which the project resides will also have access. However if the project entry is not present in the dictionary this access check passes. Args: django_args: a dictionary with django's arguments survey_logic: instance of ProjectSurveyLogic (or subclass) role_name: String containing either "student" or "mentor" project_key_location: String containing the key entry in the GET dict where the key for the project can be located. """ if not role_name in ['mentor', 'student']: raise InvalidArgumentError('role_name is not mentor or student') # check if the current user is signed up self.checkIsUser(django_args) user_entity = self.user # get the project keyname from the GET dictionary get_dict = django_args['GET'] key_name = get_dict.get(project_key_location) if not key_name: # no key name present so no need to deny access return # retrieve the Student Project for the key project_entity = student_project_logic.getFromKeyNameOr404(key_name) # check if a survey can be conducted about this project if project_entity.status != 'accepted': raise out_of_band.AccessViolation( message_fmt=DEF_NOT_ALLOWED_PROJECT_FOR_SURVEY_MSG) # get the correct role depending on the role_name if role_name == 'student': role_entity = project_entity.student elif role_name == 'mentor': role_entity = project_entity.mentor # check if the role matches the current user if role_entity.user.key() != user_entity.key() and (role_entity.status == 'active'): if role_name == 'student': raise out_of_band.AccessViolation( message_fmt=DEF_NOT_ALLOWED_PROJECT_FOR_SURVEY_MSG) elif role_name == 'mentor': # check if the current user is an Org Admin for this Student Project fields = { 'user': user_entity, 'scope': project_entity.scope, 'status': 'active' } admin_entity = org_admin_logic.getForFields(fields, unique=True) if not admin_entity: # this user is no Org Admin or Mentor for this project raise out_of_band.AccessViolation( message_fmt=DEF_NOT_ALLOWED_PROJECT_FOR_SURVEY_MSG) elif role_entity.status != 'active': # this role is not active raise out_of_band.AccessViolation( message_fmt=access.DEF_NEED_ROLE_MSG) return
def checkRoleAndStatusForStudentProposal(self, django_args, allowed_roles, role_status, proposal_status): """Checks if the current user has access to the given proposal. Args: django_args: a dictionary with django's arguments allowed_roles: list with names for the roles allowed to pass access check role_status: list with states allowed for the role proposal_status: a list with states allowed for the proposal Raises: AccessViolationResponse: - If there is no proposal found - If the proposal is not in one of the required states. - If the user does not have any ofe the required roles """ self.checkIsUser(django_args) # bail out with 404 if no proposal is found proposal_entity = student_proposal_logic.getFromKeyFieldsOr404( django_args) if not proposal_entity.status in proposal_status: # this proposal can not be accessed at the moment raise out_of_band.AccessViolation( message_fmt=access.DEF_NO_ACTIVE_ENTITY_MSG) user_entity = self.user if 'proposer' in allowed_roles: # check if this proposal belongs to the current user student_entity = proposal_entity.scope if (user_entity.key() == student_entity.user.key()) and (student_entity.status in role_status): return filter = {'user': user_entity, 'status': role_status} if 'host' in allowed_roles: # check if the current user is a host for this proposal's program filter['scope'] = proposal_entity.program.scope if host_logic.getForFields(filter, unique=True): return if 'org_admin' in allowed_roles: # check if the current user is an admin for this proposal's org filter['scope'] = proposal_entity.org if org_admin_logic.getForFields(filter, unique=True): return if 'mentor' in allowed_roles: # check if the current user is a mentor for this proposal's org filter['scope'] = proposal_entity.org if mentor_logic.getForFields(filter, unique=True): return # no roles found, access denied raise out_of_band.AccessViolation(message_fmt=access.DEF_NEED_ROLE_MSG)
def checkCanOrgAdminOrMentorEdit(self, django_args, key_location, check_limit): """Checks if the mentors can create task for this program, and obeys the task quota limit assigned for their org when check_limit is True. Args: django_args: a dictionary with django's arguments. key_location: the key for django_args in which the key_name of the org is stored. check_limit: iff true checks if the organization reached the task quota limit for the given program. """ import settings self.checkIsUser(django_args) user_account = user_logic.logic.getCurrentUser() if key_location not in django_args: raise out_of_band.AccessViolation(message_fmt=DEF_NEED_ROLE_MSG) filter = { 'user': user_account, 'scope_path': django_args[key_location], 'status': 'active' } role_entity = gci_org_admin_logic.logic.getForFields(filter, unique=True) if not role_entity: role_entity = gci_mentor_logic.logic.getForFields(filter, unique=True) if not role_entity: raise out_of_band.AccessViolation( message_fmt=DEF_SIGN_UP_AS_OA_MENTOR_MSG) # pylint: disable=E1103 program_entity = role_entity.program if not timeline_helper.isActivePeriod(program_entity.timeline, 'program'): raise out_of_band.AccessViolation( message_fmt=DEF_PAGE_INACTIVE_MSG) # pylint: disable=E1103 org_entity = role_entity.scope if settings.GCI_TASK_QUOTA_LIMIT_ENABLED and check_limit: # count all tasks from this organization fields = {'scope': org_entity} task_query = gci_task_logic.logic.getQueryForFields(fields) if task_query.count() >= org_entity.task_quota_limit: # too many tasks access denied raise out_of_band.AccessViolation( message_fmt=DEF_MAX_TASKS_REACHED_MSG) if 'link_id' in django_args: task_entity = gci_task_logic.logic.getFromKeyFieldsOr404( django_args) if task_entity.status not in [ 'Unapproved', 'Unpublished', 'Open', 'ClaimRequested', 'Reopened' ]: # task is claimed at least once raise out_of_band.AccessViolation( message_fmt=DEF_CANT_EDIT_MSG) return