def _checkDeadline_helper(method, extension, moduleObj, request, tl, *args, **kwargs): if tl != 'learn' and tl != 'teach': return (True, None) response = None canView = False if not_logged_in(request): response = HttpResponseRedirect( '%s?%s=%s' % (LOGIN_URL, REDIRECT_FIELD_NAME, quote(request.get_full_path()))) else: canView = request.user.updateOnsite(request) if not canView: perm_name = { 'learn': 'Student', 'teach': 'Teacher' }[tl] + extension canView = Permission.user_has_perm(request.user, perm_name, program=request.program) # For now, allow an exception if the user is of the wrong type # This is because we are used to UserBits having a null user affecting everyone, regardless of user type. if not canView and Permission.valid_objects().filter( permission_type=perm_name, program=request.program, user__isnull=True).exists(): canView = True return (canView, response)
def testProgramPerm(self): perm = 'Student/MainPage' other_program = Program.objects.create(grade_min=7, grade_max=12) self.create_role_perm_for_program(perm) self.assertTrue(self.user_has_perm_for_program(perm)) self.assertFalse(self.user_has_perm(perm)) self.assertFalse(Permission.user_has_perm(self.user, perm, program=other_program))
def deadline_met(self, extension=''): # Short-circuit the request middleware during testing, when we call # this function without an actual request. if hasattr(self, 'user'): user = self.user else: request = get_current_request() user = request.user if not user or not self.program: raise ESPError(False), "There is no user or program object!" if self.module.module_type != 'learn' and self.module.module_type != 'teach': return True canView = user.isOnsite(self.program) or user.isAdministrator( self.program) if not canView: deadline = { 'learn': 'Student', 'teach': 'Teacher' }[self.module.module_type] + extension canView = Permission.user_has_perm(user, deadline, program=self.program) return canView
def testRolePerm(self): perm = 'Student/MainPage' other_user = ESPUser.objects.create(username='******') self.create_role_perm_for_program(perm) self.assertTrue(self.user_has_perm_for_program(perm)) self.assertFalse( Permission.user_has_perm(other_user, perm, program=self.program))
def _checkDeadline_helper(method, extension, moduleObj, request, tl, *args, **kwargs): """ Decide if a user can view a requested page; if not, offer a redirect. Given information about a request, return a pair of type (bool, None | response), which indicates whether the user can view the requested page, and an optional redirect if not. If the user is an administrator, annotate the request with information about what roles have permission to view the requested page. """ if tl != 'learn' and tl != 'teach' and tl != 'volunteer': return (True, None) response = None canView = False perm_name = {'learn':'Student','teach':'Teacher','volunteer':'Volunteer'}[tl]+extension if not_logged_in(request): if not moduleObj.require_auth() and Permission.null_user_has_perm(permission_type=perm_name, program=request.program): canView = True else: response = HttpResponseRedirect('%s?%s=%s' % (LOGIN_URL, REDIRECT_FIELD_NAME, quote(request.get_full_path()))) else: user = request.user program = request.program canView = user.updateOnsite(request) if not canView: canView = Permission.user_has_perm(user, perm_name, program=program) # For now, allow an exception if the user is of the wrong type # This is because we are used to UserBits having a null user affecting everyone, regardless of user type. if not canView and Permission.valid_objects().filter(permission_type=perm_name, program=program, user__isnull=True).exists(): canView = True # Give administrators additional information if user.isAdministrator(program=program): request.show_perm_info = True if getattr(request, 'perm_names', None) is not None: request.perm_names.append(perm_name) else: request.perm_names = [perm_name] roles_with_perm = Permission.list_roles_with_perm(perm_name, program) if getattr(request, 'roles_with_perm', None) is not None: request.roles_with_perm += roles_with_perm else: request.roles_with_perm = roles_with_perm return (canView, response)
def ajax_schedule(self, request, tl, one, two, module, extra, prog): import json as json from django.template.loader import render_to_string context = self.prepare({}) context['prog'] = self.program context['one'] = one context['two'] = two context['reg_open'] = bool(Permission.user_has_perm(request.user, {'learn':'Student','teach':'Teacher'}[tl]+"/Classes",prog)) schedule_str = render_to_string('users/student_schedule_inline.html', context) script_str = render_to_string('users/student_schedule_inline.js', context) json_data = {'student_schedule_html': schedule_str, 'script': script_str} # Look at the 'extra' data and act appropriately: # - List, query set, or comma-separated ID list of class sections: # Add the buttons for those class sections to the returned data. # - String 'all': # Add the buttons for all of the student's class sections to the returned data # - Anything else: # Don't do anything. # Rewrite registration button if a particular section was named. (It will be in extra). sec_ids = [] if extra == 'all': # TODO(benkraft): this branch of the if was broken for 5 years and # nobody noticed, so we may be able to remove it entirely. sec_ids = self.user.getSections(self.program).values_list('id', flat=True) elif isinstance(extra, list) or isinstance(extra, QuerySet): sec_ids = list(extra) else: try: sec_ids = [int(x) for x in extra.split(',')] except: pass for sec_id in sec_ids: try: section = ClassSection.objects.get(id=sec_id) cls = section.parent_class button_context = {'sec': section, 'cls': cls} if section in request.user.getEnrolledSections(self.program): button_context['label'] = 'Registered!' button_context['disabled'] = True addbutton_str1 = render_to_string(self.baseDir()+'addbutton_fillslot.html', button_context) addbutton_str2 = render_to_string(self.baseDir()+'addbutton_catalog.html', button_context) json_data['addbutton_fillslot_sec%d_html' % sec_id] = addbutton_str1 json_data['addbutton_catalog_sec%d_html' % sec_id] = addbutton_str2 except Exception, inst: raise AjaxError('Encountered an error retrieving updated buttons: %s' % inst)
def _checkGrade(moduleObj, request, tl, *args, **kwargs): errorpage = 'errors/program/wronggrade.html' # if there's grade override we can just skip everything if Permission.user_has_perm(request.user, 'GradeOverride', moduleObj.program): return method(moduleObj, request, tl, *args, **kwargs) # now we have to use the grade.. # get the last grade... cur_grade = request.user.getGrade(moduleObj.program) if cur_grade != 0 and (cur_grade < moduleObj.program.grade_min or \ cur_grade > moduleObj.program.grade_max): return render_to_response(errorpage, request, {'yog': request.user.getYOG(moduleObj.program)}) return method(moduleObj, request, tl, *args, **kwargs)
def _checkDeadline_helper(method, extension, moduleObj, request, tl, *args, **kwargs): if tl != 'learn' and tl != 'teach': return (True, None) response = None canView = False if not_logged_in(request): response = HttpResponseRedirect('%s?%s=%s' % (LOGIN_URL, REDIRECT_FIELD_NAME, quote(request.get_full_path()))) else: canView = request.user.updateOnsite(request) if not canView: perm_name = {'learn':'Student','teach':'Teacher'}[tl]+extension canView = Permission.user_has_perm(request.user, perm_name, program=request.program) # For now, allow an exception if the user is of the wrong type # This is because we are used to UserBits having a null user affecting everyone, regardless of user type. if not canView and Permission.valid_objects().filter(permission_type=perm_name, program=request.program, user__isnull=True).exists(): canView = True return (canView, response)
def deadline_met(self, extension=''): # Short-circuit the request middleware during testing, when we call # this function without an actual request. if hasattr(self, 'user'): user = self.user else: request = get_current_request() user = request.user if not user or not self.program: raise ESPError(False), "There is no user or program object!" if self.module.module_type != 'learn' and self.module.module_type != 'teach': return True canView = user.isOnsite(self.program) or user.isAdministrator(self.program) if not canView: deadline = {'learn':'Student', 'teach':'Teacher'}[self.module.module_type]+extension canView = Permission.user_has_perm(user, deadline, program=self.program) return canView
def ajax_schedule(self, request, tl, one, two, module, extra, prog): import json as json from django.template.loader import render_to_string context = self.prepare({}) context['prog'] = self.program context['one'] = one context['two'] = two context['reg_open'] = bool( Permission.user_has_perm(request.user, { 'learn': 'Student', 'teach': 'Teacher' }[tl] + "/Classes", prog)) schedule_str = render_to_string('users/student_schedule_inline.html', context) script_str = render_to_string('users/student_schedule_inline.js', context) json_data = { 'student_schedule_html': schedule_str, 'script': script_str } # Look at the 'extra' data and act appropriately: # - List, query set, or comma-separated ID list of class sections: # Add the buttons for those class sections to the returned data. # - String 'all': # Add the buttons for all of the student's class sections to the returned data # - Anything else: # Don't do anything. # Rewrite registration button if a particular section was named. (It will be in extra). sec_ids = [] if extra == 'all': # TODO(benkraft): this branch of the if was broken for 5 years and # nobody noticed, so we may be able to remove it entirely. sec_ids = self.user.getSections(self.program).values_list( 'id', flat=True) elif isinstance(extra, list) or isinstance(extra, QuerySet): sec_ids = list(extra) else: try: sec_ids = [int(x) for x in extra.split(',')] except: pass for sec_id in sec_ids: try: section = ClassSection.objects.get(id=sec_id) cls = section.parent_class button_context = {'sec': section, 'cls': cls} if section in request.user.getEnrolledSections(self.program): button_context['label'] = 'Registered!' button_context['disabled'] = True addbutton_str1 = render_to_string( self.baseDir() + 'addbutton_fillslot.html', button_context) addbutton_str2 = render_to_string( self.baseDir() + 'addbutton_catalog.html', button_context) json_data['addbutton_fillslot_sec%d_html' % sec_id] = addbutton_str1 json_data['addbutton_catalog_sec%d_html' % sec_id] = addbutton_str2 except Exception, inst: raise AjaxError( 'Encountered an error retrieving updated buttons: %s' % inst)
def user_has_perm(self, name, *args, **kwargs): """Checks for Permission object with user=self.user.""" return Permission.user_has_perm(self.user, name, *args, **kwargs)
def testRolePerm(self): perm = 'Student/MainPage' other_user = ESPUser.objects.create(username='******') self.create_role_perm_for_program(perm) self.assertTrue(self.user_has_perm_for_program(perm)) self.assertFalse(Permission.user_has_perm(other_user, perm, program=self.program))
def classchangerequest(request, tl, one, two): from esp.program.models import Program, StudentAppResponse, StudentRegistration, RegistrationType from esp.program.models.class_ import ClassSubject from urllib import quote try: prog = Program.by_prog_inst(one, two) #DataTree.get_by_uri(treeItem) except Program.DoesNotExist: raise Http404("Program not found.") if tl != "learn": raise Http404 if not request.user or not request.user.is_authenticated(): return HttpResponseRedirect( '%s?%s=%s' % (LOGIN_URL, REDIRECT_FIELD_NAME, quote(request.get_full_path()))) if not request.user.isStudent() and not request.user.isAdmin(prog): allowed_student_types = Tag.getTag("allowed_student_types", prog, default='') matching_user_types = any( x in request.user.groups.all().values_list("name", flat=True) for x in allowed_student_types.split(",")) if not matching_user_types: return render_to_response('errors/program/notastudent.html', request, {}) errorpage = 'errors/program/wronggrade.html' cur_grade = request.user.getGrade(prog) if (not Permission.user_has_perm( request.user, 'GradeOverride', program=prog) and (cur_grade != 0 and (cur_grade < prog.grade_min or cur_grade > prog.grade_max))): return render_to_response(errorpage, request, {}) setattr(request, "program", prog) setattr(request, "tl", tl) setattr(request, "module", "classchangerequest") from django import forms from datetime import datetime from esp.utils.scheduling import getRankInClass timeslots = prog.getTimeSlots() sections = prog.sections().filter(status=10) enrollments = {} for timeslot in timeslots: try: enrollments[timeslot] = ClassSubject.objects.get( nest_Q(StudentRegistration.is_valid_qobject(), 'sections__studentregistration'), sections__studentregistration__relationship__name="Enrolled", sections__studentregistration__user=request.user, sections__meeting_times=timeslot, parent_program=prog) except ClassSubject.DoesNotExist: enrollments[timeslot] = None context = {} context['timeslots'] = timeslots context['enrollments'] = enrollments context['user'] = request.user if 'success' in request.GET: context['success'] = True else: context['success'] = False if request.user.isStudent(): sections_by_slot = dict([(timeslot, [ (section, 1 == StudentRegistration.valid_objects().filter( user=context['user'], section=section, relationship__name="Request").count()) for section in sections if section.get_meeting_times()[0] == timeslot and section.parent_class.grade_min <= request.user.getGrade( prog) <= section.parent_class.grade_max and section.parent_class not in enrollments.values() and getRankInClass(request.user, section) in (5, 10) ]) for timeslot in timeslots]) else: sections_by_slot = dict([(timeslot, [ (section, False) for section in sections if section.get_meeting_times()[0] == timeslot ]) for timeslot in timeslots]) fields = {} for i, timeslot in enumerate(sections_by_slot.keys()): choices = [('0', "I'm happy with my current enrollment.")] initial = '0' for section in sections_by_slot[timeslot]: choices.append( (section[0].emailcode(), section[0].emailcode() + ": " + section[0].title())) if section[1]: initial = section[0].emailcode() fields['timeslot_' + str(i + 1)] = forms.ChoiceField( label="Timeslot " + str(i + 1) + " (" + timeslot.pretty_time() + ")", choices=choices, initial=initial) form = type('ClassChangeRequestForm', (forms.Form, ), fields) context['form'] = form() if request.method == "POST": old_requests = StudentRegistration.valid_objects().filter( user=context['user'], section__parent_class__parent_program=prog, relationship__name="Request") for r in old_requests: r.expire() form = form(request.POST) if form.is_valid(): for value in form.cleaned_data.values(): section = None for s in sections: if s.emailcode() == value: section = s break if not section: continue r = StudentRegistration.objects.get_or_create( user=context['user'], section=section, relationship=RegistrationType.objects.get_or_create( name="Request", category="student")[0])[0] r.end_date = datetime(9999, 1, 1, 0, 0, 0, 0) r.save() return HttpResponseRedirect(request.path.rstrip('/') + '/?success') else: return render_to_response('program/classchangerequest.html', request, context)
def addclass_logic(self, request, tl, one, two, module, extra, prog): """ Pre-register the student for the class section in POST['section_id']. Return True if there are no errors. """ reg_perm = 'Student/Classes' scrmi = self.program.getModuleExtension('StudentClassRegModuleInfo') if 'prereg_verb' in request.POST: proposed_verb = "V/Flags/Registration/%s" % request.POST[ 'prereg_verb'] if scrmi.use_priority: available_verbs = [ "%s/%d" % (scrmi.signup_verb.get_uri(), x) for x in xrange(1, scrmi.priority_limit + 1) ] else: available_verbs = [scrmi.signup_verb.get_uri()] if proposed_verb in available_verbs: prereg_verb = proposed_verb else: prereg_verb = None else: prereg_verb = None # Explicitly set the user's onsiteness, since we refer to it soon. if not hasattr(request.user, "onsite_local"): request.user.onsite_local = False if request.POST.has_key('class_id'): classid = request.POST['class_id'] sectionid = request.POST['section_id'] else: raise ESPError( False ), "We've lost track of your chosen class's ID! Please try again; make sure that you've clicked the \"Add Class\" button, rather than just typing in a URL. Also, please make sure that your Web browser has JavaScript enabled." # Can we register for more than one class yet? if (not request.user.onsite_local) and (not Permission.user_has_perm( request.user, reg_perm, prog)): enrolled_classes = ESPUser(request.user).getEnrolledClasses( prog, request) # Some classes automatically register people for enforced prerequisites (i.e. HSSP ==> Spark). Don't penalize people for these... classes_registered = 0 for cls in enrolled_classes: reg_verbs = cls.getRegVerbs(request.user) is_auto = 0 for r in reg_verbs: if r == 'Automatic': is_auto = 1 if not is_auto: classes_registered += 1 if classes_registered >= 1: datestring = '' sreg_perms = Permission.objects.filter( user__isnull=True, role__name="Student", permission_type=reg_perm, program=prog) if sreg_perms.count() > 0: d = sreg_perms[0].start_date if d.date() == d.today().date(): datestring = ' later today' else: datestring = d.strftime(' on %B %d') raise ESPError( False ), "Currently, you are only allowed to register for one %s class. Please come back after student registration fully opens%s!" % ( prog.niceName(), datestring) section = ClassSection.objects.get(id=sectionid) if not scrmi.use_priority: error = section.cannotAdd(request.user, self.enforce_max) if scrmi.use_priority or not error: cobj = ClassSubject.objects.get(id=classid) error = cobj.cannotAdd(request.user, self.enforce_max) or section.cannotAdd( request.user, self.enforce_max) if scrmi.use_priority: priority = request.user.getRegistrationPriority( prog, section.meeting_times.all()) else: priority = 1 # autoregister for implied classes one level deep. XOR is currently not implemented, but we're not using it yet either. auto_classes = [] blocked_class = None cannotadd_error = '' for implication in ClassImplication.objects.filter( cls__id=classid, parent__isnull=True): if implication.fails_implication(request.user): for cls in ClassSubject.objects.filter( id__in=implication.member_id_ints): # Override size limits on subprogram classes (checkFull=False). -Michael P sec = cls.default_section() if sec.cannotAdd(request.user, checkFull=False): blocked_class = cls cannotadd_error = sec.cannotAdd(request.user, checkFull=False) else: if sec.preregister_student(request.user, overridefull=True, automatic=True, priority=priority, prereg_verb=prereg_verb): auto_classes.append(sec) if implication.operation != 'AND': break else: blocked_class = cls if (blocked_class is not None) and implication.operation == 'AND': break if implication.fails_implication(request.user): for sec in auto_classes: sec.unpreregister_student(request.user, prereg_verb=prereg_verb) if blocked_class is not None: raise ESPError( False ), 'You have no class blocks free for this class during %s! Please go to <a href="%sstudentreg">%s Student Registration</a> and make sure you have time on your schedule for the class "%s." (%s)' % ( blocked_class.parent_program.niceName(), blocked_class.parent_program.get_learn_url(), blocked_class.parent_program.niceName(), blocked_class.title(), cannotadd_error) else: raise ESPError( False ), 'You have no class blocks free for this class during %s! Please go to <a href="%sstudentreg">%s Student Registration</a> and make sure you have time on your schedule for the class. (%s)' % ( prog.niceName(), prog.get_learn_url(), prog.niceName(), cannotadd_error) if error and not request.user.onsite_local: raise ESPError(False), error # Desired priority level is 1 above current max if section.preregister_student(request.user, request.user.onsite_local, priority, prereg_verb=prereg_verb): regs = Record.objects.filter(user=request.user, program=prog, event="reg_confirmed") if regs.count() == 0 and Tag.getTag('confirm_on_addclass'): r = Record.objects.create(user=request.user, program=prog, event="reg_confirmed") return True else: raise ESPError( False ), 'According to our latest information, this class is full. Please go back and choose another class.'
def studentregphasezero(self, request, tl, one, two, module, extra, prog): """ Serves the Phase Zero student reg page. The initial page includes a button to enter the student lottery. Following entering the lottery, students are served a confirmation page. """ context = {} context['program'] = prog context['one'] = one context['two'] = two user = request.user in_lottery = PhaseZeroRecord.objects.filter(user=user, program=prog).exists() if Permission.user_has_perm(user, 'Student/Classes/PhaseZero', program=prog): if in_lottery: context['lottery_group'] = PhaseZeroRecord.objects.get( user=user, program=prog) context['lottery_size'] = context['lottery_group'].user.count() return render_to_response( 'program/modules/studentregphasezero/confirmation.html', request, context) else: if request.method == 'POST': form = SubmitForm(request.POST, program=prog) if form.is_valid(): form.save(user, prog) context['lottery_group'] = PhaseZeroRecord.objects.get( user=user, program=prog) context['lottery_size'] = context[ 'lottery_group'].user.count() self.send_confirmation_email(user) return render_to_response( 'program/modules/studentregphasezero/confirmation.html', request, context) else: form = SubmitForm(program=prog) context['form'] = form return render_to_response( 'program/modules/studentregphasezero/submit.html', request, context) else: if in_lottery: if Tag.getBooleanTag('student_lottery_run', prog, default=False): #Sorry page return render_to_response( 'program/modules/studentregphasezero/sorry.html', request, context) else: #Lottery has not yet been run page return render_to_response( 'program/modules/studentregphasezero/notyet.html', request, context) else: #Generic error page return render_to_response( 'errors/program/phasezero_closed.html', request, context)