Пример #1
0
    def handle(self, *args, **kwargs):
        if len(args) != 1:
            raise CommandError("This command accepts only one argument")

        try:
            workbook = xlrd.open_workbook(args[0])
        except IOError:
            raise CommandError("Couldn't open roster: {}".format(args[0]))

        s = workbook.sheets()[0]

        # TODO: make this more programmatic?
        FIELD_ORDERING = settings.ROSTER_FIELD_ORDERING

        senior = GradYear.senior_class(
            sem=Semester.objects.get(half=kwargs['semester'], year=kwargs['year'])
        )
        logger.info("Senior year: %s", senior)
        CLASS_TO_GRADYEAR = {
            'FE': senior + 3,  # Freshmen have three codes
            'FF': senior + 3,
            'FR': senior + 3,
            'SO': senior + 2,
            'JR': senior + 1,
            'SR': senior,
        }

        # Initialize and bind to the LDAP connection
        lconn = ldap.initialize(
                uri=settings.AUTH_LDAP_SERVER_URI,
        )
        lconn.simple_bind_s(
            who=settings.AUTH_LDAP_BIND_DN,
            cred=settings.AUTH_LDAP_BIND_PASSWORD,
        )

        # get hmc for easy access later
        hmc = Campus.objects.get(code='HM')
        this_sem, _ = Semester.objects.get_or_create(
            year=kwargs['year'],
            half=kwargs['semester'],
        )
        logger.info("Semester: %s", this_sem)

        active_users = []
        for r in xrange(settings.ROSTER_ROW_START, s.nrows):
            row = s.row(r)

            try:
                gradyear = CLASS_TO_GRADYEAR[row[FIELD_ORDERING.index('Class')].value]
            except KeyError:
                logger.error("%d No such class: %s", r, row[FIELD_ORDERING.index('Class')].value)
                continue

            # Skip people who've already graduated - we don't care about them
            if gradyear < CLASS_TO_GRADYEAR['SR'] and not kwargs['old_data']:
                continue

            email = row[FIELD_ORDERING.index('Email')].value
            try:
                new_user = User.objects.get(
                    email=email,
                )
                active_users += [new_user.id]
            except ObjectDoesNotExist:
                # Check LDAP for user
                student_results = lconn.search_s(
                    "OU=Academic Students,DC=HMC,DC=EDU", ldap.SCOPE_SUBTREE, filterstr="(mail={})".format(
                        email,
                    )
                )

                if len(student_results) < 1:
                    logger.error("%d Couldn't find user with email %s", r, email)
                    continue
                elif len(student_results) > 1:
                    logger.error("%d Multiple students matching email %s", r, email)
                    continue

                ldap_student = student_results[0][1]

                try:
                    new_user = User.objects.create_user(
                        username=ldap_student['sAMAccountName'][0],
                        email=email,
                    )
                except Exception:
                    new_user = User.objects.get(
                        username=ldap_student['sAMAccountName'][0],
                    )
                    # In case they were previously inactivated...
                    new_user.is_active = True

                new_user.first_name = ldap_student['givenName'][0]
                new_user.last_name = ldap_student['sn'][0]
                new_user.save()
                # keep track of which users we HAVE seen this time through
                active_users += [new_user.id]

                new_student, _ = Student.objects.get_or_create(
                    user=new_user,
                    class_of=gradyear,
                    at=hmc,
                    studentid=None,
                )

            dormcode = row[FIELD_ORDERING.index('Dorm')].value.split(' ')

            if dormcode[0] == '':
                logger.error("%d Couldn't match dormcode %s", r, dormcode)
                continue

            # Roster has CGUA, whereas DB has CGA.
            if dormcode[0].startswith("CGU"):
                dormcode = "CG{}".format(dormcode[0][-1])
            else:
                dormcode = dormcode[0]

            try:
                dorm = Dorm.all_objects.get(code__iexact=dormcode)
            except ObjectDoesNotExist:
                # If all else fails, see if there's a name match
                logger.warn("No such code %s - trying name match", dormcode)
                try:
                    dorm = Dorm.all_objects.get(name__istartswith=dormcode)
                except (ObjectDoesNotExist, MultipleObjectsReturned):
                    logger.error(
                        "{} ldap population failed for {} (on failed dorm lookup {}) - assuming OFF".format(r, new_user, dormcode),
                    )
                    dorm = Dorm.objects.get(code="OFF")

            if dorm.code == "OFF":
                room = DormRoom.objects.get(
                    dorm=dorm,
                    number="Symbolic Room",
                )

            else:
                number = row[FIELD_ORDERING.index("Room")].value,
                try:
                    number = int(number)
                except ValueError:
                    number = str(number)

                room, _ = DormRoom.objects.get_or_create(
                    dorm=dorm,
                    number=number,
                )

            if dorm.code in Dorm.all_objects.filter(official_dorm=False).values_list('code', flat=True)\
              and dorm.code != "ABR":
                # If they're off-campus, make sure they're 'symbollically'
                # a part of the Offcampus dorm for voting purposes.
                symoff, _ = DormRoom.objects.get_or_create(
                    dorm__code="OFF",
                    number="Symbolic Room",
                )

                # Symroom is going to be full of people.
                symroomur, _ = UserRoom.objects.get_or_create(
                    user=new_user,
                    room=symoff,
                )
                symroomur.semesters.add(this_sem)

                logger.info("Created symoblic room entry for %s", new_user)

            ur, _ = UserRoom.objects.get_or_create(
                user=new_user,
                room=room,
            )
            ur.semesters.add(this_sem)

        # inactivate missing users - except the super.
        for user in User.objects.exclude(is_superuser=True).exclude(id__in=active_users):
            logger.info("Inactivating {}".format(user.username))
            user.is_active = False
            user.save()
Пример #2
0
    def handle(self, *args, **kwargs):
        if len(args) != 1:
            raise CommandError("This command accepts only one argument")

        try:
            workbook = xlrd.open_workbook(args[0])
        except IOError:
            raise CommandError("Couldn't open workbook: {}".format(args[0]))

        s = workbook.sheets()[0]

        # On what row does the actual information start?
        ROSTER_ROW_START = 3

        # TODO: make this more programmatic?
        FIELD_ORDERING = [
            'ID',
            'Fullname',
            'Nickname',
            'Class',
            'Dorm',
            'Room',
            'Phonenumber',
            'Email Address',
        ]
        senior = GradYear.senior_class(
            sem=Semester.objects.get(half=kwargs['semester'], year=kwargs['year'])
        ).year
        CLASS_TO_GRADYEAR = {
            'FE': senior + 3,
            'FF': senior + 3,
            'FR': senior + 3,
            'SO': senior + 2,
            'JR': senior + 1,
            'SR': senior,
        }

        for r in xrange(ROSTER_ROW_START, s.nrows):
            row = s.row(r)

            year = CLASS_TO_GRADYEAR[row[FIELD_ORDERING.index('Class')].value]

            if year < GradYear.senior_class().year and not kwargs['old_data']:
                continue

            gradyear, _ = GradYear.objects.get_or_create(
                year=year,
            )
            print row

            hmc = Campus.objects.get(code='HM')

            fullname = row[FIELD_ORDERING.index('Fullname')].value
            l_f_m_name = fullname.split(', ')
            last_name = l_f_m_name[0]
            f_m_name = ', '.join(l_f_m_name[1:]).split(' ')
            first_name = f_m_name[0]
            middle_name = ''

            temp_password = User.objects.make_random_password()

            try:
                new_user = User.objects.get(email=row[FIELD_ORDERING.index('Email Address')].value.lower().replace('hmc.edu', 'g.hmc.edu'))
            except ObjectDoesNotExist:
                new_user = User.objects.create_user(
                    username=row[FIELD_ORDERING.index('Email Address')].value.lower().replace('hmc.edu', 'g.hmc.edu'),
                    email=row[FIELD_ORDERING.index('Email Address')].value.lower().replace('hmc.edu', 'g.hmc.edu'),
                    password=temp_password,
                )

            new_user.first_name = first_name
            new_user.last_name = last_name

            new_user.save()
            studentid = int(row[FIELD_ORDERING.index('ID')].value),
            studentid = None
            new_student, _ = Student.objects.get_or_create(
                user=new_user,
                class_of=gradyear,
                at=hmc,
                studentid=studentid,
            )

            new_student.middle_name = middle_name
            new_student.temp_pass = temp_password

            new_student.save()

            dormname = row[FIELD_ORDERING.index('Dorm')].value.split(' ')

            if dormname[0] != '':
                if dormname[0] == "CGU":
                    dormname = ' '.join(dormname)
                else:
                    dormname = dormname[0]

                dorm = Dorm.objects.get(name__startswith=dormname)

                room, _ = DormRoom.objects.get_or_create(
                    dorm=dorm,
                    number=row[FIELD_ORDERING.index("Room")].value,
                )

                ur, _ = UserRoom.objects.get_or_create(
                    user=new_user,
                    room=room,
                )

                ur.semesters.add(Semester.objects.get(half=kwargs['semester'], year=int(kwargs['year'])))
Пример #3
0
    def handle(self, *args, **kwargs):
        if len(args) != 1:
            raise CommandError("This command accepts only one argument")

        try:
            workbook = xlrd.open_workbook(args[0])
        except IOError:
            raise CommandError("Couldn't open workbook: {}".format(args[0]))

        s = workbook.sheets()[0]

        # On what row does the actual information start?
        ROSTER_ROW_START = 3

        # TODO: make this more programmatic?
        FIELD_ORDERING = ["ID", "Fullname", "Nickname", "Class", "Dorm", "Room", "Phonenumber", "Email Address"]
        senior = GradYear.senior_class(sem=Semester.objects.get(half=kwargs["semester"], year=kwargs["year"])).year
        CLASS_TO_GRADYEAR = {
            "FE": senior + 3,
            "FF": senior + 3,
            "FR": senior + 3,
            "SO": senior + 2,
            "JR": senior + 1,
            "SR": senior,
        }

        for r in xrange(ROSTER_ROW_START, s.nrows):
            row = s.row(r)

            year = CLASS_TO_GRADYEAR[row[FIELD_ORDERING.index("Class")].value]

            if year < GradYear.senior_class().year and not kwargs["old_data"]:
                continue

            gradyear, _ = GradYear.objects.get_or_create(year=year)
            print row

            hmc = Campus.objects.get(code="HM")

            fullname = row[FIELD_ORDERING.index("Fullname")].value
            l_f_m_name = fullname.split(", ")
            last_name = l_f_m_name[0]
            f_m_name = ", ".join(l_f_m_name[1:]).split(" ")
            first_name = f_m_name[0]
            middle_name = ""

            temp_password = User.objects.make_random_password()

            try:
                new_user = User.objects.get(
                    email=row[FIELD_ORDERING.index("Email Address")].value.lower().replace("hmc.edu", "g.hmc.edu")
                )
            except ObjectDoesNotExist:
                new_user = User.objects.create_user(
                    username=row[FIELD_ORDERING.index("Email Address")].value.lower().replace("hmc.edu", "g.hmc.edu"),
                    email=row[FIELD_ORDERING.index("Email Address")].value.lower().replace("hmc.edu", "g.hmc.edu"),
                    password=temp_password,
                )

            new_user.first_name = first_name
            new_user.last_name = last_name

            new_user.save()
            studentid = (int(row[FIELD_ORDERING.index("ID")].value),)
            studentid = None
            new_student, _ = Student.objects.get_or_create(
                user=new_user, class_of=gradyear, at=hmc, studentid=studentid
            )

            new_student.middle_name = (middle_name,)
            new_student.temp_pass = (temp_password,)

            new_student.save()

            dormname = row[FIELD_ORDERING.index("Dorm")].value.split(" ")

            if dormname[0] != "":
                if dormname[0] == "CGU":
                    dormname = " ".join(dormname)
                else:
                    dormname = dormname[0]

                dorm = Dorm.objects.get(name__startswith=dormname)

                room, _ = DormRoom.objects.get_or_create(dorm=dorm, number=row[FIELD_ORDERING.index("Room")].value)

                ur, _ = UserRoom.objects.get_or_create(user=new_user, room=room)

                ur.semesters.add(Semester.objects.get(half=kwargs["semester"], year=int(kwargs["year"])))
Пример #4
0
def create_user_related_things(*args, **kwargs):
    if 'user' not in kwargs or 'ldap_user' not in kwargs:
        return

    new_user = kwargs['user']
    print new_user, new_user.email
    # don't repopulate if we've already done the dance.
    if Student.objects.filter(user=new_user).count():
        logger.debug("skipping student {}".format(new_user))
        return

    logger.info("new student {}".format(new_user))

    try:
        this_sem = Semester.get_this_semester()
        workbook = xlrd.open_workbook(settings.ROSTER_DIRECTORY + "{}.xlsx".format(
            this_sem.verbose_unicode()
        ))
    except IOError:
        logger.error("could not open workbook {}".format(this_sem.verbose_unicode()))
        return

    s = workbook.sheets()[0]

    # On what row does the actual information start?
    ROSTER_ROW_START = settings.ROSTER_ROW_START

    # TODO: make this more programmatic?
    FIELD_ORDERING = settings.ROSTER_FIELD_ORDERING

    senior = GradYear.senior_class(
        sem=this_sem,
    ).year
    if settings.DEBUG:
        print "\tsenior year:", senior
    CLASS_TO_GRADYEAR = {
        'FE': senior + 3,
        'FF': senior + 3,
        'FR': senior + 3,
        'SO': senior + 2,
        'JR': senior + 1,
        'SR': senior,
    }
    try:
        for r in xrange(ROSTER_ROW_START, s.nrows):
            row = s.row(r)

            if row[FIELD_ORDERING.index('Email')].value != new_user.email:
                logger.debug("\tSkipping row", r, row[FIELD_ORDERING.index('Email')].value)
                continue

            logger.debug("creating user-related things...")
            year = CLASS_TO_GRADYEAR[row[FIELD_ORDERING.index('Class')].value]

            gradyear, _ = GradYear.objects.get_or_create(
                year=year,
            )

            hmc = Campus.objects.get(code='HM')

            studentid = None
            new_student, _ = Student.objects.get_or_create(
                user=new_user,
                class_of=gradyear,
                at=hmc,
                studentid=studentid,
                phonenumber=row[FIELD_ORDERING.index('Phone')].value,
                #birthdate=datetime.datetime.strptime(row[FIELD_ORDERING.index('Birthdate')].value, '%b %d, %Y').date(),
            )

            dormcode = row[FIELD_ORDERING.index('Dorm')].value.split(' ')

            if dormcode[0] != '':
                # Roster has CGUA, whereas DB has CGA.
                if dormcode[0] == "CGU":
                    dormcode = ' '.join(dormcode)
                else:
                    dormcode = dormcode[0]

                try:
                    dorm = Dorm.objects.get(code__iexact=dormcode)
                except ObjectDoesNotExist:
                    try:
                        dorm = Dorm.objects.get(name__istartswith=dormcode)
                    except (ObjectDoesNotExist, MultipleObjectsReturned):
                        logger.error(
                            "ldap population failed for {} (on failed dorm lookup {})".format(new_user, dormcode)
                        )
                        return

                room, _ = DormRoom.objects.get_or_create(
                    dorm=dorm,
                    number=row[FIELD_ORDERING.index("Room")].value,
                )

                if dorm.code in Dorm.all_objects.filter(official_dorm=False).values_list('code', flat=True)\
                  and dorm.code != "ABR":
                    # If they're off-campus, make sure they're 'symbollically'
                    # a part of the Offcampus dorm.
                    symoff, _ = DormRoom.objects.get_or_create(
                        dorm__code="OFF",
                        number="Symbolic Room",
                    )

                    # Symroom is going to be full of people.
                    symroomur, _ = UserRoom.objects.get_or_create(
                        user=new_user,
                        room=symoff,
                    )
                    symroomur.semesters.add(this_sem)

                ur, _ = UserRoom.objects.get_or_create(
                    user=new_user,
                    room=room,
                )
                ur.semesters.add(this_sem)

            return
    except Exception, e:
        # Don't interrupt core service, no matter what.
        logger.error("caught unhandled exception {}: {}".format(e, e.message))
        return
Пример #5
0
    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')