def get(self, *args, **kwargs): # Only the upper eschelons of the council can create measures. # President, VP, Dorm President, and Class Presidents only. # And super users, obviously. userrole = ASHMCAppointment.get_current_highest(self.request.user) minimum_role = ASHMCRole.objects.get(title=ASHMCRole.COUNCIL_ROLES[2]) if userrole < minimum_role: if "Class President" not in userrole.title: raise PermissionDenied() return super(CreateMeasure, self).get(*args, **kwargs)
def post(self, *args, **kwargs): # block POSTs from most people. userrole = ASHMCAppointment.get_current_highest(self.request.user) minimum_role = ASHMCRole.objects.get(title=ASHMCRole.COUNCIL_ROLES[2]) if userrole < minimum_role: if "Class President" not in userrole.title: raise PermissionDenied() form_class = self.get_form_class() # This setting to None is a hack to make the get_form call work. self.object = None form = self.get_form(form_class) if not form.is_valid(): return self.form_invalid(form) print form.cleaned_data # The measure itself is valid; create it. new_measure = Measure.objects.create( name=form.cleaned_data['name'], vote_start=form.cleaned_data['vote_start'], vote_end=form.cleaned_data['vote_end'], summary=form.cleaned_data['summary'], quorum=form.cleaned_data['quorum'], is_open=form.cleaned_data['is_open'], ) logger.info("Created measure %d", new_measure.id) # This doesn't currently allow banned_accounts to be added. You need # use the regular admin for that. if isinstance(self.request.user.highest_ashmc_role.cast(), DormPresident): # Dorm presidents can only send measures to their dorm. logger.debug("dorm president dorm restriction") real_role = self.request.user.highest_ashmc_role.cast() dorm_restrictions = [real_role.dorm] elif self.request.user.highest_ashmc_role > ASHMCRole.objects.get( title=ASHMCRole.COUNCIL_ROLES[3]): logger.debug("unrestricted dorm restriction") # VP and president can restrict dorm as they choose. dorm_restrictions = Dorm.objects.filter( pk__in=self.request.POST.getlist('dorms')) else: logger.debug("no dorm restriction allowed") dorm_restrictions = [] if self.request.user.highest_ashmc_role.title.endswith( "Class President"): logger.debug("Enacting class-president restriction") # Year-based class presidents can only send measure to their constituencies. if self.request.user.highest_ashmc_role.title.startswith("Senior"): year_restrictions = [GradYear.senior_class()] elif self.request.user.highest_ashmc_role.title.startswith( "Junior"): year_restrictions = [GradYear.senior_class() - 1] elif self.request.user.highest_ashmc_role.title.startswith( "Sophomore"): year_restrictions = [GradYear.senior_class() - 2] else: year_restrictions = [GradYear.senior_class() - 3] else: year_restrictions = GradYear.objects.filter( pk__in=self.request.POST.getlist('gradyears')) # Update the Restrictions object for this new_measure. restrictions = new_measure.restrictions restrictions.gradyears.add(*[gy for gy in year_restrictions]) restrictions.dorms.add(*[d for d in dorm_restrictions]) # Now, ballot creation. # Ballots fields all look like r"(\d+)_.*". # There will always be at least one ballot; gather all the specified # attributes in a ballots_dict, to be used later to create the actual ballots # and candidates. ballots_dict = {} for key in self.request.POST: if not re.match(r"^\d+_", key): continue if self.request.POST[key] == "on": keyval = True else: keyval = self.request.POST[key] ballot_sep_index = key.index('_') ballot_num = int(key[:ballot_sep_index]) # create an empty dict with ballot num as key if it doesn't already exist. ballots_dict.setdefault(ballot_num, {}) key_rest = key[ballot_sep_index + 1:] if re.match(r"\d+_", key_rest): # this is a candidate field -- they will always start with # r"\d+_\d+_" ballots_dict[ballot_num].setdefault('candidates', {}) candidate_sep_index = key_rest.index('_') candidate_num = int(key_rest[:candidate_sep_index]) key_rest_rest = key_rest[candidate_sep_index + 1:] ballots_dict[ballot_num]['candidates'].setdefault( candidate_num, {}) ballots_dict[ballot_num]['candidates'][candidate_num][ key_rest_rest] = keyval else: # this is a ballot field. ballots_dict[ballot_num][key_rest] = keyval for ballot_num in ballots_dict: ballot_dict = ballots_dict[ballot_num] # sanitize ballot info for key, val in ballot_dict.items(): if val == "": del ballot_dict[key] if "can_abstain" not in ballot_dict: ballot_dict["can_abstain"] = False candidate_info = ballot_dict.pop('candidates', {}) ballot = Ballot.objects.create(measure=new_measure, **ballot_dict) logger.info("M%d: created ballot %d", new_measure.id, ballot.id) for candidate_num in candidate_info.keys(): candidate_dict = candidate_info[candidate_num] is_person = candidate_dict.pop('is_person', False) if is_person: usernames = candidate_dict['title'].split(' ') try: # Only support username students = Student.objects.filter( user__username__in=usernames) # if there's any problems, give up and create a normal # candidate. if not students: logger.warn("Could not find usernames: {}".format( usernames)) raise Student.DoesNotExist( "Could not find usernames: {}".format( usernames)) elif len(students) != len(usernames): logger.warn( "Could not find all usernames: {} (found {})". format(usernames, students)) raise Student.DoesNotExist( "Could not find all usernames: {} (found {})". format(usernames, students)) candidate = PersonCandidate.objects.create( ballot=ballot, **candidate_dict) logger.info("M%dB%d: created person candidate for %s", new_measure.id, ballot.id, students) for student in students: CandidateUser.objects.create( user=student.user, person_candidate=candidate, ) except Student.DoesNotExist: logger.warn( "M%dB%d: creating fallback candidate (instead of person candidate)", new_measure.id, ballot.id) candidate = Candidate.objects.create(ballot=ballot, **candidate_dict) print 'new candy keys:', candidate_info.keys() else: candidate = Candidate.objects.create(ballot=ballot, **candidate_dict) logger.info("M%dB%d: created candidate %d", new_measure.id, ballot.id, candidate.id) # Finally, take them to the measure list. return redirect('measure_list')
def post(self, *args, **kwargs): # block POSTs from most people. userrole = ASHMCAppointment.get_current_highest(self.request.user) minimum_role = ASHMCRole.objects.get(title=ASHMCRole.COUNCIL_ROLES[2]) if userrole < minimum_role: if "Class President" not in userrole.title: raise PermissionDenied() form_class = self.get_form_class() # This setting to None is a hack to make the get_form call work. self.object = None form = self.get_form(form_class) if not form.is_valid(): return self.form_invalid(form) print form.cleaned_data # The measure itself is valid; create it. new_measure = Measure.objects.create( name=form.cleaned_data['name'], vote_start=form.cleaned_data['vote_start'], vote_end=form.cleaned_data['vote_end'], summary=form.cleaned_data['summary'], quorum=form.cleaned_data['quorum'], is_open=form.cleaned_data['is_open'], ) logger.info("Created measure %d", new_measure.id) # This doesn't currently allow banned_accounts to be added. You need # use the regular admin for that. if isinstance(self.request.user.highest_ashmc_role.cast(), DormPresident): # Dorm presidents can only send measures to their dorm. logger.debug("dorm president dorm restriction") real_role = self.request.user.highest_ashmc_role.cast() dorm_restrictions = [real_role.dorm] elif self.request.user.highest_ashmc_role > ASHMCRole.objects.get(title=ASHMCRole.COUNCIL_ROLES[3]): logger.debug("unrestricted dorm restriction") # VP and president can restrict dorm as they choose. dorm_restrictions = Dorm.objects.filter(pk__in=self.request.POST.getlist('dorms')) else: logger.debug("no dorm restriction allowed") dorm_restrictions = [] if self.request.user.highest_ashmc_role.title.endswith("Class President"): logger.debug("Enacting class-president restriction") # Year-based class presidents can only send measure to their constituencies. if self.request.user.highest_ashmc_role.title.startswith("Senior"): year_restrictions = [GradYear.senior_class()] elif self.request.user.highest_ashmc_role.title.startswith("Junior"): year_restrictions = [GradYear.senior_class() - 1] elif self.request.user.highest_ashmc_role.title.startswith("Sophomore"): year_restrictions = [GradYear.senior_class() - 2] else: year_restrictions = [GradYear.senior_class() - 3] else: year_restrictions = GradYear.objects.filter(pk__in=self.request.POST.getlist('gradyears')) # Update the Restrictions object for this new_measure. restrictions = new_measure.restrictions restrictions.gradyears.add(*[gy for gy in year_restrictions]) restrictions.dorms.add(*[d for d in dorm_restrictions]) # Now, ballot creation. # Ballots fields all look like r"(\d+)_.*". # There will always be at least one ballot; gather all the specified # attributes in a ballots_dict, to be used later to create the actual ballots # and candidates. ballots_dict = {} for key in self.request.POST: if not re.match(r"^\d+_", key): continue if self.request.POST[key] == "on": keyval = True else: keyval = self.request.POST[key] ballot_sep_index = key.index('_') ballot_num = int(key[:ballot_sep_index]) # create an empty dict with ballot num as key if it doesn't already exist. ballots_dict.setdefault(ballot_num, {}) key_rest = key[ballot_sep_index + 1:] if re.match(r"\d+_", key_rest): # this is a candidate field -- they will always start with # r"\d+_\d+_" ballots_dict[ballot_num].setdefault('candidates', {}) candidate_sep_index = key_rest.index('_') candidate_num = int(key_rest[:candidate_sep_index]) key_rest_rest = key_rest[candidate_sep_index + 1:] ballots_dict[ballot_num]['candidates'].setdefault(candidate_num, {}) ballots_dict[ballot_num]['candidates'][candidate_num][key_rest_rest] = keyval else: # this is a ballot field. ballots_dict[ballot_num][key_rest] = keyval for ballot_num in ballots_dict: ballot_dict = ballots_dict[ballot_num] # sanitize ballot info for key, val in ballot_dict.items(): if val == "": del ballot_dict[key] if "can_abstain" not in ballot_dict: ballot_dict["can_abstain"] = False candidate_info = ballot_dict.pop('candidates', {}) ballot = Ballot.objects.create(measure=new_measure, **ballot_dict) logger.info("M%d: created ballot %d", new_measure.id, ballot.id) for candidate_num in candidate_info.keys(): candidate_dict = candidate_info[candidate_num] is_person = candidate_dict.pop('is_person', False) if is_person: usernames = candidate_dict['title'].split(' ') try: # Only support username students = Student.objects.filter(user__username__in=usernames) # if there's any problems, give up and create a normal # candidate. if not students: logger.warn("Could not find usernames: {}".format(usernames)) raise Student.DoesNotExist("Could not find usernames: {}".format(usernames)) elif len(students) != len(usernames): logger.warn("Could not find all usernames: {} (found {})".format(usernames, students)) raise Student.DoesNotExist( "Could not find all usernames: {} (found {})".format(usernames, students) ) candidate = PersonCandidate.objects.create( ballot=ballot, **candidate_dict ) logger.info("M%dB%d: created person candidate for %s", new_measure.id, ballot.id, students) for student in students: CandidateUser.objects.create( user=student.user, person_candidate=candidate, ) except Student.DoesNotExist: logger.warn("M%dB%d: creating fallback candidate (instead of person candidate)", new_measure.id, ballot.id) candidate = Candidate.objects.create( ballot=ballot, **candidate_dict ) print 'new candy keys:', candidate_info.keys() else: candidate = Candidate.objects.create( ballot=ballot, **candidate_dict ) logger.info("M%dB%d: created candidate %d", new_measure.id, ballot.id, candidate.id) # Finally, take them to the measure list. return redirect('measure_list')