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 _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_qsd(request): """ Ajax function for in-line QSD editing. """ from django.utils import simplejson from esp.lib.templatetags.markdown import markdown result = {} post_dict = request.POST.copy() if (request.user.id is None): return HttpResponse( content= 'Oops! Your session expired!\nPlease open another window, log in, and try again.\nYour changes will not be lost if you keep this page open.', status=500) if post_dict['cmd'] == "update": qsd = QuasiStaticData.objects.get(id=post_dict['id']) if not Permission.user_can_edit_qsd(request.user, qsd.url): return HttpResponse( content='Sorry, you do not have permission to edit this page.', status=500) # Since QSD now uses reversion, we want to only modify the data if we've actually changed something # The revision will automatically be created upon calling the save function of the model object if qsd.content != post_dict['data']: qsd.content = post_dict['data'] qsd.load_cur_user_time(request, ) qsd.save() # We should also purge the cache purge_page(qsd.url + ".html") result['status'] = 1 result['content'] = markdown(qsd.content) result['id'] = qsd.id if post_dict['cmd'] == "create": if not Permission.user_can_edit_qsd(request.user, post_dict['url']): return HttpResponse( content="Sorry, you do not have permission to edit this page.", status=500) qsd, created = QuasiStaticData.objects.get_or_create( url=post_dict['url'], defaults={'author': request.user}) qsd.content = post_dict['data'] qsd.author = request.user qsd.save() result['status'] = 1 result['content'] = markdown(qsd.content) result['id'] = qsd.id return HttpResponse(simplejson.dumps(result))
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 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 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 ajax_qsd(request): """ Ajax function for in-line QSD editing. """ import json from markdown import markdown result = {} post_dict = request.POST.copy() if ( request.user.id is None ): return HttpResponse(content='Oops! Your session expired!\nPlease open another window, log in, and try again.\nYour changes will not be lost if you keep this page open.', status=401) if post_dict['cmd'] == "update": if not Permission.user_can_edit_qsd(request.user, post_dict['url']): return HttpResponse(content='Sorry, you do not have permission to edit this page.', status=403) qsd, created = QuasiStaticData.objects.get_or_create(url=post_dict['url'], defaults={'author': request.user}) # Since QSD now uses reversion, we want to only modify the data if we've actually changed something # The revision will automatically be created upon calling the save function of the model object if qsd.content != post_dict['data']: qsd.content = post_dict['data'] qsd.load_cur_user_time(request, ) qsd.save() # We should also purge the cache purge_page(qsd.url+".html") result['status'] = 1 result['content'] = markdown(qsd.content) result['url'] = qsd.url return HttpResponse(json.dumps(result))
def registration_redirect(request): """ A view which returns: - A redirect to the currently open registration if exactly one registration is open - A list of open registration links otherwise """ from esp.users.models import ESPUser from esp.program.models import Program # Make sure we have an ESPUser user = ESPUser(request.user) # prepare the rendered page so it points them to open student/teacher reg's ctxt = {} userrole = {} regperm = None if user.isStudent(): userrole['name'] = 'Student' userrole['base'] = 'learn' userrole['reg'] = 'studentreg' regperm = 'Student/Classes' elif user.isTeacher(): userrole['name'] = 'Teacher' userrole['base'] = 'teach' userrole['reg'] = 'teacherreg' regperm = 'Teacher/Classes' else: # Default to student registration (this will only show if the program # is found via the 'allowed_student_types' Tag) userrole['name'] = user.getUserTypes()[0] userrole['base'] = 'learn' userrole['reg'] = 'studentreg' ctxt['userrole'] = userrole if regperm: progs_deadline = list(Permission.program_by_perm(user, regperm)) else: progs_deadline = [] progs_tag = list(t.target \ for t in Tag.objects.filter(key = "allowed_student_types").select_related() \ if isinstance(t.target, Program) \ and (set(user.getUserTypes()) & set(t.value.split(",")))) progs = list(set(progs_deadline + progs_tag)) #distinct ones # If we have 1 program, automatically redirect to registration for that program. # Most chapters will want this, but it can be disabled by a Tag. if len(progs) == 1 and Tag.getBooleanTag('automatic_registration_redirect', default=True): ctxt['prog'] = progs[0] return HttpResponseRedirect( u'/%s/%s/%s' % (userrole['base'], progs[0].getUrlBase(), userrole['reg'])) else: if len(progs) > 0: # Sort available programs newest first progs.sort(key=lambda x: -x.id) ctxt['progs'] = progs ctxt['prog'] = progs[0] return render_to_response('users/profile_complete.html', request, ctxt)
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 lottery(self, prog, role): # Run lottery algorithm. # Get grade caps grade_caps_str = prog.grade_caps() grade_caps = { int(key[0]): value for key, value in grade_caps_str.iteritems() } #Get lottery records and randomize them records = PhaseZeroRecord.objects.filter(program=prog).order_by('?') ############################################################################### # The lottery algorithm is run, with randomization and processing in order. # If any one in the group doesn't get in (due to cap size), no one in that group gets in. counts = {key: 0 for key in grade_caps} winners, _ = Group.objects.get_or_create(name=role) for i in records: sibs = i.user.all() newcounts = copy.copy(counts) for j in sibs: newcounts[j.getGrade(prog)] += 1 cpass = not any(newcounts[c] > grade_caps[c] for c in counts) if cpass: winners.user_set.add(*sibs) counts = newcounts ############################################################################### # Post lottery, assign permissions to people in the lottery winners group # Assign OverridePhaseZero permission and Student/All permissions override_perm = Permission(permission_type='OverridePhaseZero', role=winners, start_date=datetime.datetime.now(), program=prog) studentAll_perm = Permission(permission_type='Student/All', role=winners, start_date=datetime.datetime.now(), program=prog) override_perm.save() studentAll_perm.save() # Add tag to indicate student lottery has been run Tag.setTag('student_lottery_run', target=prog, value='True') return True
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 myesp_onsite(request): user = request.user if not user.isOnsite(): raise ESPError('You are not a valid on-site user, please go away.', log=False) progs = Permission.program_by_perm(user,"Onsite") # Order them decreasing by id # - Currently reverse the list in Python, otherwise fbap's cache is ignored # TODO: Fix this progs = list(progs) progs.reverse() if len(progs) == 1: return HttpResponseRedirect('/onsite/%s/main' % progs[0].getUrlBase()) else: return render_to_response('program/pickonsite.html', request, {'progs': progs})
def registration_redirect(request): """ A view which returns: - A redirect to the currently open registration if exactly one registration is open - A list of open registration links otherwise """ from esp.users.models import ESPUser from esp.program.models import Program user = request.user # prepare the rendered page so it points them to open student/teacher reg's ctxt = {} userrole = {} regperm = None if user.isStudent(): userrole['name'] = 'Student' userrole['base'] = 'learn' userrole['reg'] = 'studentreg' regperm = 'Student/Classes' elif user.isTeacher(): userrole['name'] = 'Teacher' userrole['base'] = 'teach' userrole['reg'] = 'teacherreg' regperm = 'Teacher/Classes' ctxt['userrole'] = userrole if regperm: progs = list(Permission.program_by_perm(user,regperm)) else: progs = [] # If we have 1 program, automatically redirect to registration for that program. # Most chapters will want this, but it can be disabled by a Tag. if len(progs) == 1 and Tag.getBooleanTag('automatic_registration_redirect', default=True): ctxt['prog'] = progs[0] return HttpResponseRedirect(u'/%s/%s/%s' % (userrole['base'], progs[0].getUrlBase(), userrole['reg'])) else: if len(progs) > 0: # Sort available programs newest first progs.sort(key=lambda x: -x.id) ctxt['progs'] = progs ctxt['prog'] = progs[0] return render_to_response('users/profile_complete.html', request, ctxt)
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 render(self, context): try: user = self.user_variable.resolve(context) if self.user_variable is not None else None except template.VariableDoesNotExist: user = None try: program = self.program_variable.resolve(context) if self.program_variable is not None else None except template.VariableDoesNotExist: program = None # Accept literal string url argument if it is quoted; otherwise expect a template variable. if not self.url.startswith('"'): url_resolved = template.Variable(self.url).resolve(context) else: url_resolved = self.url.strip('"') if program is not None: url = QuasiStaticData.prog_qsd_url(program,url_resolved) else: url = url_resolved #probably should have an error message if variable was not None and prog was edit_bits = Permission.user_can_edit_qsd(user, url) qsd_obj = QuasiStaticData.objects.get_by_url(url) if qsd_obj == None: new_qsd = QuasiStaticData() new_qsd.url = url new_qsd.title = url new_qsd.content = self.nodelist.render(context) if getattr(user, 'id', False): new_qsd.author = user new_qsd.save() qsd_obj = new_qsd return render_to_response("inclusion/qsd/render_qsd_inline.html", {'qsdrec': qsd_obj, 'edit_bits': edit_bits}, context_instance=context).content
def deadline_management(self, request, tl, one, two, module, extra, prog): # Define a formset for editing multiple perms simultaneously. EditPermissionFormset = formset_factory(EditPermissionForm) # Define a status message message = '' # Handle 'open' / 'close' actions if extra == 'open' and 'id' in request.GET: perm = Permission.objects.get(id=request.GET['id']) # Clear any duplicate user permissions Permission.objects.filter( permission_type=perm.permission_type, program=perm.program, user__isnull=True, role=perm.role).exclude(id=perm.id).delete() perm.end_date = None perm.save() message = 'Deadline opened: %s.' % perm.nice_name() elif extra == 'close' and 'id' in request.GET: perm = Permission.objects.get(id=request.GET['id']) # Clear any duplicate user permissions Permission.objects.filter( permission_type=perm.permission_type, program=perm.program, user__isnull=True, role=perm.role).exclude(id=perm.id).delete() perm.end_date = datetime.now() perm.save() message = 'Deadline closed: %s.' % perm.nice_name() # Check incoming form data if request.method == 'POST': edit_formset = EditPermissionFormset(request.POST.copy(), prefix='edit') create_form = NewPermissionForm(request.POST.copy()) if edit_formset.is_valid(): num_forms = 0 for form in edit_formset.forms: # Check if the permission with the specified ID exists. # It may have been deleted by previous iterations of this loop # deleting duplicate permissions. if 'id' in form.cleaned_data and Permission.objects.filter( id=form.cleaned_data['id']).exists(): num_forms += 1 perm = Permission.objects.get( id=form.cleaned_data['id']) # Clear any duplicate perms Permission.objects.filter( permission_type=perm.permission_type, program=perm.program, user__isnull=True, role=perm.role).exclude(id=perm.id).delete() perm.start_date = form.cleaned_data['start_date'] perm.end_date = form.cleaned_data['end_date'] perm.save() if num_forms > 0: message = 'Changes saved.' if create_form.is_valid(): perm, created = Permission.objects.get_or_create( user=None, permission_type=create_form. cleaned_data['permission_type'], role=Group.objects.get( name=create_form.cleaned_data['role']), program=prog) if not created: message = 'Deadline already exists: %s. Please modify the existing deadline.' % perm.nice_name( ) else: perm.start_date = create_form.cleaned_data['start_date'] perm.end_date = create_form.cleaned_data['end_date'] perm.save() message = 'Deadline created: %s.' % perm.nice_name() else: message = 'No activities selected. Please select a deadline type from the list before creating a deadline.' # find all the existing permissions with this program # Only consider global permissions -- those that apply to all users # of a particular role. Permissions added for individual users # should be managed in the admin interface. perms = Permission.deadlines().filter(program=self.program, user__isnull=True) perm_map = {p.permission_type: p for p in perms} # Populate template context to render page with forms context = {} # Set a flag on each perm for whether it has ended # TODO(benkraft): refactor users to just call is_valid themselves. for perm in perms: perm.open_now = perm.is_valid() # For each permission, determine which other ones it implies for perm in perms: includes = Permission.implications.get(perm.permission_type, []) perm.includes = [] perm.name = perm.nice_name() for p in includes: if p == perm.permission_type: continue perm.includes.append({ 'type': p, 'nice_name': Permission.nice_name_lookup(p) }) if p in perm_map: perm.includes[-1].update({ 'overridden': True, 'overridden_by': perm_map[p], 'bit_open': perm_map[p].open_now }) # Supply initial data for forms formset = EditPermissionFormset( initial=[perm.__dict__ for perm in perms], prefix='edit') for i in range(len(perms)): perms[i].form = formset.forms[i] context['message'] = message context['manage_form'] = formset.management_form context['perms'] = perms context['create_form'] = NewPermissionForm() return render_to_response(self.baseDir() + 'deadlines.html', request, context)
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 qsd(request, url): # Extract the 'action' from the supplied URL if there is one url_parts = url.split('/') page_name = url_parts[-1] page_name_parts = page_name.split('.') if len(page_name_parts) > 1: action = page_name_parts[-1] page_name_base = '.'.join(page_name_parts[:-1]) else: action = 'read' page_name_base = page_name base_url = '/'.join(url_parts[:-1] + [page_name_base]) # Detect edit authorizations have_read = True if not have_read and action == 'read': raise Http403, "You do not have permission to access this page." # Fetch the QSD object try: qsd_rec = QuasiStaticData.objects.get_by_url(base_url) if qsd_rec == None: raise QuasiStaticData.DoesNotExist if qsd_rec.disabled: raise QuasiStaticData.DoesNotExist except QuasiStaticData.DoesNotExist: have_edit = Permission.user_can_edit_qsd(request.user, base_url) if have_edit: if action in ( 'edit', 'create', ): qsd_rec = QuasiStaticData() qsd_rec.url = base_url qsd_rec.nav_category = NavBarCategory.default() qsd_rec.title = 'New Page' qsd_rec.content = 'Please insert your text here' qsd_rec.create_date = datetime.now() qsd_rec.keywords = '' qsd_rec.description = '' action = 'edit' if (action == 'read'): edit_link = '/' + base_url + '.edit.html' return render_to_response('qsd/nopage_create.html', request, {'edit_link': edit_link}, use_request_context=False) else: if action == 'read': raise Http404, 'This page does not exist.' else: raise Http403, 'Sorry, you can not modify <tt>%s</tt>.' % request.path if action == 'create': action = 'edit' # Detect the standard read verb if action == 'read': if not have_read: raise Http403, 'You do not have permission to read this page.' # Render response response = render_to_response( 'qsd/qsd.html', request, { 'title': qsd_rec.title, 'nav_category': qsd_rec.nav_category, 'content': qsd_rec.html(), 'settings': settings, 'qsdrec': qsd_rec, 'have_edit': True, ## Edit-ness is determined client-side these days 'edit_url': '/' + base_url + ".edit.html" }, use_request_context=False) # patch_vary_headers(response, ['Cookie']) # if have_edit: # add_never_cache_headers(response) # patch_cache_control(response, no_cache=True, no_store=True) # else: patch_cache_control(response, max_age=3600, public=True) return response # Detect POST if request.POST.has_key('post_edit'): have_edit = Permission.user_can_edit_qsd(request.user, base_url) if not have_edit: raise Http403, "Sorry, you do not have permission to edit this page." nav_category_target = NavBarCategory.objects.get( id=request.POST['nav_category']) # Since QSD now uses reversion, we want to only modify the data if we've actually changed something # The revision will automatically be created upon calling the save function of the model object if qsd_rec.url != base_url or qsd_rec.nav_category != nav_category_target or qsd_rec.content != request.POST[ 'content'] or qsd_rec.description != request.POST[ 'description'] or qsd_rec.keywords != request.POST[ 'keywords']: qsd_rec.url = base_url qsd_rec.nav_category = NavBarCategory.objects.get( id=request.POST['nav_category']) qsd_rec.content = request.POST['content'] qsd_rec.title = request.POST['title'] qsd_rec.description = request.POST['description'] qsd_rec.keywords = request.POST['keywords'] qsd_rec.load_cur_user_time(request) qsd_rec.save() # We should also purge the cache purge_page(qsd_rec.url + ".html") # If any files were uploaded, save them for name, file in request.FILES.iteritems(): m = Media() # Strip "media/" from FILE, and strip the file name; just return the path path = dirname(name[9:]) # Do we want a better/manual mechanism for setting friendly_name? m.friendly_name = basename(name) m.format = '' local_filename = name if name[:9] == 'qsdmedia/': local_filename = name[9:] m.handle_file(file, local_filename) m.save() # Detect the edit verb if action == 'edit': have_edit = Permission.user_can_edit_qsd(request.user, base_url) # Enforce authorizations (FIXME: SHOW A REAL ERROR!) if not have_edit: raise ESPError( False), "You don't have permission to edit this page." m = ESPMarkdown(qsd_rec.content, media={}) m.toString() # assert False, m.BrokenLinks() # Render an edit form return render_to_response( 'qsd/qsd_edit.html', request, { 'title': qsd_rec.title, 'content': qsd_rec.content, 'keywords': qsd_rec.keywords, 'description': qsd_rec.description, 'nav_category': qsd_rec.nav_category, 'nav_categories': NavBarCategory.objects.all(), 'qsdrec': qsd_rec, 'qsd': True, 'missing_files': m.BrokenLinks(), 'target_url': base_url.split("/")[-1] + ".edit.html", 'return_to_view': base_url.split("/")[-1] + ".html#refresh" }, use_request_context=False) # Operation Complete! raise Http404('Unexpected QSD operation')
def qsd(request, url): # Extract the 'action' from the supplied URL if there is one url_parts = url.split('/') page_name = url_parts[-1] page_name_parts = page_name.split('.') if len(page_name_parts) > 1: action = page_name_parts[-1] page_name_base = '.'.join(page_name_parts[:-1]) else: action = 'read' page_name_base = page_name base_url = '/'.join(url_parts[:-1] + [page_name_base]) # Detect edit authorizations have_read = True if not have_read and action == 'read': raise Http403, "You do not have permission to access this page." # Fetch the QSD object try: qsd_rec = QuasiStaticData.objects.get_by_url(base_url) if qsd_rec == None: raise QuasiStaticData.DoesNotExist if qsd_rec.disabled: raise QuasiStaticData.DoesNotExist except QuasiStaticData.DoesNotExist: have_edit = Permission.user_can_edit_qsd(request.user, base_url) if have_edit: if action in ('edit','create',): qsd_rec = QuasiStaticData() qsd_rec.url = base_url qsd_rec.nav_category = default_navbarcategory() qsd_rec.title = 'New Page' qsd_rec.content = 'Please insert your text here' qsd_rec.create_date = datetime.now() qsd_rec.keywords = '' qsd_rec.description = '' action = 'edit' if (action == 'read'): edit_link = '/' + base_url + '.edit.html' response = render_to_response('qsd/nopage_create.html', request, {'edit_link': edit_link}, use_request_context=False) response.status_code = 404 # Make sure we actually 404, so that if there is a redirect the middleware can catch it. return response else: if action == 'read': raise Http404, 'This page does not exist.' else: raise Http403, 'Sorry, you can not modify <tt>%s</tt>.' % request.path if action == 'create': action = 'edit' # Detect the standard read verb if action == 'read': if not have_read: raise Http403, 'You do not have permission to read this page.' # Render response response = render_to_response('qsd/qsd.html', request, { 'title': qsd_rec.title, 'nav_category': qsd_rec.nav_category, 'content': qsd_rec.html(), 'settings': settings, 'qsdrec': qsd_rec, 'have_edit': True, ## Edit-ness is determined client-side these days 'edit_url': '/' + base_url + ".edit.html" }, use_request_context=False) # patch_vary_headers(response, ['Cookie']) # if have_edit: # add_never_cache_headers(response) # patch_cache_control(response, no_cache=True, no_store=True) # else: patch_cache_control(response, max_age=3600, public=True) return response # Detect POST if 'post_edit' in request.POST: have_edit = Permission.user_can_edit_qsd(request.user, base_url) if not have_edit: raise Http403, "Sorry, you do not have permission to edit this page." nav_category_target = NavBarCategory.objects.get(id=request.POST['nav_category']) # Since QSD now uses reversion, we want to only modify the data if we've actually changed something # The revision will automatically be created upon calling the save function of the model object copy_map = { 'url': base_url, 'nav_category': nav_category_target, 'content': request.POST['content'], 'title': request.POST['title'], 'description': request.POST['description'], 'keywords': request.POST['keywords'], } diff_found = False for field, new_value in copy_map.items(): if getattr(qsd_rec, field) != new_value: setattr(qsd_rec, field, new_value) diff_found = True if diff_found: qsd_rec.load_cur_user_time(request) qsd_rec.save() # We should also purge the cache purge_page(qsd_rec.url+".html") # Detect the edit verb if action == 'edit': have_edit = Permission.user_can_edit_qsd(request.user, base_url) # Enforce authorizations (FIXME: SHOW A REAL ERROR!) if not have_edit: raise Http403, "You don't have permission to edit this page." # Render an edit form return render_to_response('qsd/qsd_edit.html', request, { 'title' : qsd_rec.title, 'content' : qsd_rec.content, 'keywords' : qsd_rec.keywords, 'description' : qsd_rec.description, 'nav_category' : qsd_rec.nav_category, 'nav_categories': NavBarCategory.objects.all(), 'qsdrec' : qsd_rec, 'qsd' : True, 'target_url' : base_url.split("/")[-1] + ".edit.html", 'return_to_view': base_url.split("/")[-1] + ".html#refresh" }, use_request_context=False) # Operation Complete! raise Http404('Unexpected QSD operation')
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)
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 deadline_management(self, request, tl, one, two, module, extra, prog): # Define a formset for editing multiple perms simultaneously. EditPermissionFormset = formset_factory(EditPermissionForm) # Define a status message message = '' # Handle 'open' / 'close' actions if extra == 'open' and 'id' in request.GET: perm = Permission.objects.get(id=request.GET['id']) # Clear any duplicate user permissions Permission.objects.filter(permission_type=perm.permission_type, program=perm.program, user__isnull=True, role=perm.role).exclude(id=perm.id).delete() perm.end_date = None perm.save() message = 'Deadline opened: %s.' % perm.nice_name() elif extra == 'close' and 'id' in request.GET: perm = Permission.objects.get(id=request.GET['id']) # Clear any duplicate user permissions Permission.objects.filter(permission_type=perm.permission_type, program=perm.program, user__isnull=True, role=perm.role).exclude(id=perm.id).delete() perm.end_date = datetime.now() perm.save() message = 'Deadline closed: %s.' % perm.nice_name() # Check incoming form data if request.method == 'POST': edit_formset = EditPermissionFormset(request.POST.copy(), prefix='edit') create_form = NewPermissionForm(request.POST.copy()) if edit_formset.is_valid(): num_forms = 0 for form in edit_formset.forms: # Check if the permission with the specified ID exists. # It may have been deleted by previous iterations of this loop # deleting duplicate permissions. if 'id' in form.cleaned_data and Permission.objects.filter(id=form.cleaned_data['id']).exists(): num_forms += 1 perm = Permission.objects.get(id=form.cleaned_data['id']) # Clear any duplicate perms Permission.objects.filter(permission_type=perm.permission_type, program=perm.program, user__isnull=True, role=perm.role).exclude(id=perm.id).delete() perm.start_date = form.cleaned_data['start_date'] perm.end_date = form.cleaned_data['end_date'] perm.save() if num_forms > 0: message = 'Changes saved.' if create_form.is_valid(): perm, created = Permission.objects.get_or_create(user=None, permission_type=create_form.cleaned_data['permission_type'], role=Group.objects.get(name=create_form.cleaned_data['role']),program=prog) if not created: message = 'Deadline already exists: %s. Please modify the existing deadline.' % perm.nice_name() else: perm.start_date = create_form.cleaned_data['start_date'] perm.end_date = create_form.cleaned_data['end_date'] perm.save() message = 'Deadline created: %s.' % perm.nice_name() else: message = 'No activities selected. Please select a deadline type from the list before creating a deadline.' # find all the existing permissions with this program # Only consider global permissions -- those that apply to all users # of a particular role. Permissions added for individual users # should be managed in the admin interface. perms = Permission.deadlines().filter(program=self.program, user__isnull=True) perm_map = {p.permission_type: p for p in perms} # Populate template context to render page with forms context = {} # Set a flag on each perm for whether it has ended # TODO(benkraft): refactor users to just call is_valid themselves. for perm in perms: perm.open_now = perm.is_valid() # For each permission, determine which other ones it implies for perm in perms: includes = Permission.implications.get(perm.permission_type, []) perm.includes = [] perm.name = perm.nice_name() for p in includes: if p == perm.permission_type: continue perm.includes.append({'type':p,'nice_name':Permission.nice_name_lookup(p)}) if p in perm_map: perm.includes[-1].update({'overridden':True, 'overridden_by':perm_map[p], 'bit_open':perm_map[p].open_now}) # Supply initial data for forms formset = EditPermissionFormset(initial = [perm.__dict__ for perm in perms], prefix = 'edit') for i in range(len(perms)): perms[i].form = formset.forms[i] context['message'] = message context['manage_form'] = formset.management_form context['perms'] = perms context['create_form'] = NewPermissionForm() return render_to_response(self.baseDir()+'deadlines.html', request, context)
def gen_perm(tup): new_perm=Permission(permission_type=tup[0], program=prog) if tup[2]: new_perm.start_date = tup[2] if tup[3]: new_perm.end_date = tup[3] if tup[1] is not None: new_perm.user=tup[1] new_perm.save() return elif tup[1] is None and tup[0].startswith("Student"): new_perm.role=Group.objects.get(name="Student") new_perm.save() return elif tup[1] is None and tup[0].startswith("Teacher"): new_perm.role=Group.objects.get(name="Teacher") new_perm.save() return #It's not for a specific user and not a teacher or student deadline for x in ESPUser.getTypes(): newnew_perm=Permission(permission_type=new_perm.permission_type, role=Group.objects.get(name=x), start_date=new_perm.start_date, end_date=new_perm.end_date, program=prog) newnew_perm.save()
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 forwards(self, orm): def end(bit): date = bit.enddate if date > datetime.datetime(3000, 1, 1): return None return date #Administer adm_bits = UserBit.objects.filter(verb__uri="V/Administer", qsc__uri__startswith="Q/Programs") for bit in adm_bits: try: p = Program.objects.get(anchor=bit.qsc) except Program.DoesNotExist: continue Permission(permission_type="Administer", program=p, user=bit.user, startdate=bit.startdate, enddate=end(bit)).save() # Administer all programs, but with an enddate. # Adds users that we didn't add to the Administrator group in 0019_userrole. for bit in UserBit.objects.filter(verb__uri="V/Administer", qsc__uri="Q", user__isnull=False, enddate__lt=datetime.datetime( 3000, 1, 1)): Permission(permission_type="Administer", program=None, user=bit.user, startdate=bit.startdate, enddate=end(bit)).save() #view programs program_anchors = Program.objects.all().values_list("anchor", flat=True) view_program_bits = UserBit.objects.filter(verb__uri="V/Flags/Public", qsc__id__in=program_anchors) for bit in view_program_bits: try: p = Program.objects.get(anchor=bit.qsc) except Program.DoesNotExist: continue if bit.user is not None: Permission(permission_type=bit.verb.uri[24:], user=bit.user, program=p, startdate=bit.startdate, enddate=end(bit)).save() else: for x in ESPUser.getTypes(): Permission(permission_type=bit.verb.uri[24:], role=Group.objects.get(name=x), program=p, startdate=bit.startdate, enddate=end(bit)).save() #gradeoverride go_bits = UserBit.objects.filter( verb__uri="V/Flags/Registration/GradeOverride", qsc__uri__startswith="Q/Programs") for bit in go_bits: try: p = Program.objects.get(anchor=bit.qsc) except Program.DoesNotExist: continue Permission(permission_type="GradeOverride", program=p, user=bit.user, startdate=bit.startdate, enddate=end(bit)).save() #onsite onsite_bits = UserBit.objects.filter(verb__uri="V/Registration/Onsite") for bit in onsite_bits: try: p = Program.objects.get(anchor=bit.qsc) except Program.DoesNotExist: continue Permission(permission_type="Onsite", user=bit.user, program=p, startdate=bit.startdate, enddate=end(bit)).save() #deadlines deadline_bits = UserBit.objects.filter( verb__uri__startswith="V/Deadline/Registration") for bit in deadline_bits: try: p = Program.objects.get(anchor=bit.qsc) except Program.DoesNotExist: continue name = bit.verb.uri[24:] if bit.recursive and bit.verb.name in [ "Classes", "Teacher", "Student" ]: name += "/All" if bit.user is not None: Permission(permission_type=name, user=bit.user, program=p, startdate=bit.startdate, enddate=end(bit)).save() elif bit.verb.uri[24:31] == "Teacher": Permission(permission_type=name, role=Group.objects.get(name="Teacher"), program=p, startdate=bit.startdate, enddate=end(bit)).save() elif bit.verb.uri[24:31] == "Student": Permission(permission_type=name, role=Group.objects.get(name="Student"), program=p, startdate=bit.startdate, enddate=end(bit)).save()
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 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 gen_perm(tup): new_perm = Permission(permission_type=tup[0], program=prog) if tup[2]: new_perm.start_date = tup[2] if tup[3]: new_perm.end_date = tup[3] if tup[1] is not None: new_perm.user = tup[1] new_perm.save() return elif tup[1] is None and tup[0].startswith("Student"): new_perm.role = Group.objects.get(name="Student") new_perm.save() return elif tup[1] is None and tup[0].startswith("Teacher"): new_perm.role = Group.objects.get(name="Teacher") new_perm.save() return #It's not for a specific user and not a teacher or student deadline for x in ESPUser.getTypes(): newnew_perm = Permission(permission_type=new_perm.permission_type, role=Group.objects.get(name=x), start_date=new_perm.start_date, end_date=new_perm.end_date, program=prog) newnew_perm.save()