Changeset 88a856b


Ignore:
Timestamp:
Dec 3, 2013, 12:20:41 AM (12 years ago)
Author:
Alex Dehnert <adehnert@…>
Branches:
master, stable, stage
Children:
d66942f
Parents:
3d2db0b
git-author:
Alex Dehnert <adehnert@…> (11/30/13 02:19:15)
git-committer:
Alex Dehnert <adehnert@…> (12/03/13 00:20:41)
Message:

Basic people lookup support (ASA-#186)

Mostly working, but the UI could use more work, and we need support for looking
up more people at once.

Location:
asadb
Files:
2 added
3 edited

Legend:

Unmodified
Added
Removed
  • asadb/forms/models.py

    re4a35ff r88a856b  
    11import datetime
    2 import os, errno
     2import errno
     3import json
     4import os
     5
     6import ldap
    37
    48from django.conf import settings
     9from django.contrib.auth.models import User
    510from django.db import models
    611
     
    207212
    208213
     214class PeopleStatusLookup(models.Model):
     215    people = models.TextField(help_text="Enter some usernames or email addresses to look up here.")
     216    requestor = models.ForeignKey(User, null=True, blank=True, )
     217    referer = models.URLField(blank=True)
     218    time = models.DateTimeField(default=datetime.datetime.now)
     219    classified_people_json = models.TextField()
     220    _classified_people = None
     221
     222    def ldap_classify(self, usernames, ):
     223        con = ldap.open('ldap-too.mit.edu')
     224        con.simple_bind_s("", "")
     225        dn = "ou=users,ou=moira,dc=mit,dc=edu"
     226        fields = ['uid', 'eduPersonAffiliation', 'mitDirStudentYear']
     227
     228        filters = [ldap.filter.filter_format('(uid=%s)', [u]) for u in usernames]
     229        userfilter = "(|%s)" % (''.join(filters), )
     230        results = con.search_s(dn, ldap.SCOPE_SUBTREE, userfilter, fields)
     231
     232        left = set(usernames)
     233        undergrads = []
     234        grads = []
     235        staff = []
     236        secret = []
     237        other = []
     238        info = {
     239            'undergrads': undergrads,
     240            'grads': grads,
     241            'staff': staff,
     242            'secret': secret,
     243            'affiliate': other,
     244        }
     245        descriptions = {
     246            'undergrads': 'Undergraduate students',
     247            'grads': 'Graduate students',
     248            'staff': 'MIT Staff (including faculty)',
     249            'secret': 'People with directory information suppressed. These people have Athena accounts, but they could have any MIT affiliation, including just being a student group member.',
     250            'affiliate': 'This includes some alumni, group members with Athena accounts sponsored through SAO, and many others.',
     251        }
     252        for result in results:
     253            username = result[1]['uid'][0]
     254            left.remove(username)
     255            affiliation = result[1].get('eduPersonAffiliation', ['secret'])[0]
     256            if affiliation == 'student':
     257                year = result[1].get('mitDirStudentYear', [None])[0]
     258                if year == 'G':
     259                    grads.append(username)
     260                elif year.isdigit():
     261                    undergrads.append((username, year))
     262                else:
     263                    other.append((username, year))
     264            else:
     265                info[affiliation].append(username)
     266        info['unknown'] = left
     267        descriptions['unknown'] = "While this looks like an Athena account, we couldn't find it. This could be a deactivated account, or it might never have existed."
     268        return descriptions, info
     269
     270    def classify_people(self, people):
     271        mit_usernames = set()
     272        alum_addresses = set()
     273        other_mit_addresses = set()
     274        nonmit_addresses = set()
     275
     276        for name in people:
     277            local, at, domain = name.partition('@')
     278            if domain.lower() == 'mit.edu' or domain == '':
     279                mit_usernames.add(local)
     280            elif domain.lower() == 'alum.mit.edu':
     281                alum_addresses.add(name)
     282            elif domain.endswith('.mit.edu'):
     283                other_mit_addresses.add(name)
     284            else:
     285                nonmit_addresses.add(name)
     286
     287        descriptions, results = self.ldap_classify(mit_usernames)
     288        descriptions['alum'] = "Alumni Association addresses"
     289        descriptions['other-mit'] = ".mit.edu addresses that aren't @mit.edu or @alum.mit.edu."
     290        descriptions['non-mit'] = "Non-MIT addresses, including outside addresses of MIT students."
     291        results['alum'] = alum_addresses
     292        results['other-mit'] = other_mit_addresses
     293        results['non-mit'] = nonmit_addresses
     294
     295        sorted_results = {}
     296        for k, v in results.items():
     297            sorted_results[k] = {
     298                'description': descriptions[k],
     299                'people': sorted(v),
     300            }
     301        return sorted_results
     302
     303    def update_classified_people(self):
     304        people = [p.strip() for p in self.people.split('\n')]
     305        print people
     306        self._classified_people = self.classify_people(people)
     307        self.classified_people_json = json.dumps(self._classified_people)
     308        return self._classified_people
     309
     310    @property
     311    def classified_people(self):
     312        if self._classified_people is None:
     313            self._classified_people = json.loads(self.classified_people_json)
     314        return self._classified_people
     315
    209316
    210317##########
  • asadb/forms/views.py

    re4a35ff r88a856b  
    559559
    560560
     561class PeopleStatusLookupForm(ModelForm):
     562    class Meta:
     563        model = forms.models.PeopleStatusLookup
     564        fields = ('people', )
     565
     566def people_status_lookup(request, pk=None, ):
     567    if pk is None:
     568        if request.method == 'POST':
     569            form = PeopleStatusLookupForm(request.POST, request.FILES, )
     570            if form.is_valid(): # All validation rules pass
     571                lookup = form.save(commit=False)
     572                lookup.requestor = request.user
     573                lookup.referer = request.META['HTTP_REFERER']
     574                results = lookup.update_classified_people()
     575                lookup.save()
     576        else:
     577            form = PeopleStatusLookupForm()
     578            results = None
     579    else:
     580        if request.user.has_perm('forms.view_peoplestatusupdate'):
     581            lookup = get_object_or_404(forms.models.PeopleStatusLookup, pk=int(pk))
     582            results = lookup.classified_people
     583            form = None
     584        else:
     585            raise PermissionDenied("You don't have permission to view old lookup requests.")
     586
     587    context = {
     588        'form': form,
     589        'results': results,
     590    }
     591
     592    return render_to_response('membership/people-lookup.html', context, context_instance=RequestContext(request), )
    561593
    562594##########
  • asadb/urls.py

    rbeb46fb r88a856b  
    6767    url(r'^membership/admin/$', forms.views.View_GroupConfirmationCyclesList.as_view(), name='membership-admin', ),
    6868    url(r'^membership/admin/issues/(?P<slug>[\w-]+).csv$', forms.views.group_confirmation_issues, name='membership-issues', ),
     69    url(r'^membership/people-lookup/((?P<pk>\d+)/)?$', forms.views.people_status_lookup, name='membership-people-lookup', ),
    6970
    7071    # Midway
Note: See TracChangeset for help on using the changeset viewer.