- Timestamp:
- Dec 3, 2013, 12:31:49 AM (12 years ago)
- Branches:
- master, stable, stage
- Children:
- eab727a
- Parents:
- 7dde669 (diff), d9624e8 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent. - git-author:
- Alex Dehnert <adehnert@…> (12/03/13 00:31:49)
- git-committer:
- Alex Dehnert <adehnert@…> (12/03/13 00:31:49)
- Location:
- asadb
- Files:
-
- 2 added
- 13 edited
-
forms/migrations/0016_peoplestatuslookup.py (added)
-
forms/models.py (modified) (3 diffs)
-
forms/views.py (modified) (9 diffs)
-
groups/models.py (modified) (6 diffs)
-
template/base.html (modified) (1 diff)
-
template/fysm/fysm_listing.html (modified) (1 diff)
-
template/groups/group_change_officers.html (modified) (1 diff)
-
template/membership/admin.html (modified) (1 diff)
-
template/membership/confirm.html (modified) (3 diffs)
-
template/membership/people-lookup.html (added)
-
template/membership/thanks.html (modified) (1 diff)
-
template/membership/update.html (modified) (2 diffs)
-
urls.py (modified) (1 diff)
-
groups/views.py (modified) (3 diffs)
-
template/groups/create/startup_review.html (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
asadb/forms/models.py
re0ed952 red7ddec 1 1 import datetime 2 import os, errno 2 import errno 3 import json 4 import os 5 6 import ldap 3 7 4 8 from django.conf import settings 9 from django.contrib.auth.models import User 5 10 from django.db import models 6 11 … … 168 173 num_other = models.IntegerField(verbose_name="Num non-MIT") 169 174 170 membership_list = models.TextField( help_text="Member emails on separate lines (Athena usernames where applicable)")175 membership_list = models.TextField(blank=True, help_text="Member emails on separate lines (Athena usernames where applicable)") 171 176 172 177 email_preface = models.TextField(blank=True, help_text="If you would like, you may add text here that will preface the text of the policies when it is sent out to the group membership list provided above.") … … 207 212 208 213 214 class 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 chunk_size = 100 229 username_chunks = [] 230 ends = range(chunk_size, len(usernames), chunk_size) 231 start = 0 232 for end in ends: 233 username_chunks.append(usernames[start:end]) 234 start = end 235 username_chunks.append(usernames[end:]) 236 print username_chunks 237 238 results = [] 239 for chunk in username_chunks: 240 filters = [ldap.filter.filter_format('(uid=%s)', [u]) for u in chunk] 241 userfilter = "(|%s)" % (''.join(filters), ) 242 batch_results = con.search_s(dn, ldap.SCOPE_SUBTREE, userfilter, fields) 243 results.extend(batch_results) 244 245 left = set(usernames) 246 undergrads = [] 247 grads = [] 248 staff = [] 249 secret = [] 250 other = [] 251 info = { 252 'undergrads': undergrads, 253 'grads': grads, 254 'staff': staff, 255 'secret': secret, 256 'affiliate': other, 257 } 258 for result in results: 259 username = result[1]['uid'][0] 260 left.remove(username) 261 affiliation = result[1].get('eduPersonAffiliation', ['secret'])[0] 262 if affiliation == 'student': 263 year = result[1].get('mitDirStudentYear', [None])[0] 264 if year == 'G': 265 grads.append((username, None)) 266 elif year.isdigit(): 267 undergrads.append((username, year)) 268 else: 269 other.append((username, year)) 270 else: 271 info[affiliation].append((username, None, )) 272 info['unknown'] = [(u, None) for u in left] 273 return info 274 275 def classify_people(self, people): 276 mit_usernames = [] 277 alum_addresses = [] 278 other_mit_addresses = [] 279 nonmit_addresses = [] 280 281 for name in people: 282 local, at, domain = name.partition('@') 283 if domain.lower() == 'mit.edu' or domain == '': 284 mit_usernames.append(local) 285 elif domain.lower() == 'alum.mit.edu': 286 alum_addresses.append((name, None)) 287 elif domain.endswith('.mit.edu'): 288 other_mit_addresses.append((name, None)) 289 else: 290 nonmit_addresses.append((name, None)) 291 292 results = self.ldap_classify(mit_usernames) 293 results['alum'] = alum_addresses 294 results['other-mit'] = other_mit_addresses 295 results['non-mit'] = nonmit_addresses 296 return results 297 298 def update_classified_people(self): 299 people = [p for p in [p.strip() for p in self.people.split('\n')] if p] 300 self._classified_people = self.classify_people(people) 301 self.classified_people_json = json.dumps(self._classified_people) 302 return self._classified_people 303 304 @property 305 def classified_people(self): 306 if self._classified_people is None: 307 self._classified_people = json.loads(self.classified_people_json) 308 return self._classified_people 309 310 def classifications_with_descriptions(self): 311 descriptions = { 312 'undergrads': 'Undergraduate students (class year in parentheses)', 313 'grads': 'Graduate students', 314 'alum': "Alumni Association addresses", 315 'staff': 'MIT Staff (including faculty)', 316 'affiliate': 'This includes some alumni, group members with Athena accounts sponsored through SAO, and many others.', 317 '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.', 318 '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.", 319 'other-mit': ".mit.edu addresses that aren't @mit.edu or @alum.mit.edu.", 320 'non-mit': "Non-MIT addresses, including outside addresses of MIT students.", 321 } 322 323 names = ( 324 ('undergrads', 'Undergrads', ), 325 ('grads', 'Grad students', ), 326 ('alum', 'Alumni', ), 327 ('staff', 'Staff', ), 328 ('affiliate', 'Affiliates', ), 329 ('secret', 'Secret', ), 330 ('unknown', 'Unknown', ), 331 ('other-mit', 'Other MIT addresses', ), 332 ('non-mit', 'Non-MIT addresses', ), 333 ) 334 335 classifications = self.classified_people 336 sorted_results = [] 337 for k, label in names: 338 sorted_results.append({ 339 'label': label, 340 'description': descriptions[k], 341 'people': sorted(classifications[k]), 342 }) 343 return sorted_results 344 209 345 210 346 ########## -
asadb/forms/views.py
re0ed952 rd9624e8 252 252 cycle = forms.models.GroupConfirmationCycle.latest() 253 253 254 users_groups = groups.models.Group. involved_groups(request.user.username)254 users_groups = groups.models.Group.admin_groups(request.user.username) 255 255 qs = membership_update_qs.filter(pk__in=users_groups) 256 256 … … 261 261 queryset=qs, 262 262 title="Submit membership update for...", 263 msg="The list below contains only groups that list you as being involved. You must be an administrator of a group to submit an update.",264 263 ) 265 264 … … 268 267 super(Form_GroupMembershipUpdate, self).__init__(*args, **kwargs) 269 268 self.fields['no_hazing'].required = True 269 help_text = "If you have a membership list, you can get help turning it into membership breakdown using our <a href='%s'>people lookup</a> tool. You'll need to copy the numbers back over, though." % (reverse('membership-people-lookup'), ) 270 self.fields['num_undergrads'].help_text = help_text 270 271 271 272 class Meta: … … 284 285 'num_other_affiliate', 285 286 'num_other', 286 'membership_list',287 #'membership_list', 287 288 ] 288 289 … … 418 419 role_groups[office_holder.group.pk] = (office_holder.group, set()) 419 420 role_groups[office_holder.group.pk][1].add(office_holder.role.display_name) 420 421 # Find groups the user searched for422 filterset = groups.views.GroupFilter(request.GET, membership_update_qs)423 filtered_groups = filterset.qs.all()424 show_filtered_groups = ('search' in request.GET)425 421 426 422 message = "" … … 469 465 'role_groups':role_groups, 470 466 'form':form, 471 'filter':filterset,472 'show_filtered_groups':show_filtered_groups,473 'filtered_groups':filtered_groups,474 467 'member_groups':selected_groups, 475 468 'message': message, … … 499 492 500 493 494 class View_GroupConfirmationCyclesList(ListView): 495 context_object_name = "cycle_list" 496 template_name = "membership/admin.html" 497 model = forms.models.GroupConfirmationCycle 498 499 def get_context_data(self, **kwargs): 500 context = super(View_GroupConfirmationCyclesList, self).get_context_data(**kwargs) 501 context['pagename'] = 'groups' 502 return context 503 504 501 505 @permission_required('groups.view_group_private_info') 502 def group_confirmation_issues(request, ):506 def group_confirmation_issues(request, slug, ): 503 507 account_numbers = ("accounts" in request.GET) and request.GET['accounts'] == "1" 504 508 505 active_groups = groups.models.Group.active_groups 506 group_updates = forms.models.GroupMembershipUpdate.objects.all() 509 check_groups = groups.models.Group.objects.filter(group_status__slug__in=('active', 'suspended', )) 510 check_groups = check_groups.select_related('group_status') 511 group_updates = forms.models.GroupMembershipUpdate.objects.filter(cycle__slug=slug, ) 512 group_updates = group_updates.select_related('group', 'group__group_status') 507 513 people_confirmations = forms.models.PersonMembershipUpdate.objects.filter( 508 514 deleted__isnull=True, 509 515 valid__gt=0, 516 cycle__slug=slug, 510 517 ) 511 518 512 519 buf = StringIO.StringIO() 513 520 output = csv.writer(buf) 514 fields = ['group_id', 'group_name', ' issue', 'num_confirm', 'officer_email', ]521 fields = ['group_id', 'group_name', 'group_status', 'issue', 'num_confirm', 'officer_email', ] 515 522 if account_numbers: fields.append("main_account") 516 523 output.writerow(fields) 517 524 518 q_present = Q(id__in=group_updates.values('group')) 519 missing_groups = active_groups.filter(~q_present) 520 #print len(list(group_updates)) 521 for group in missing_groups: 522 num_confirms = len(people_confirmations.filter(groups=group)) 525 def output_issue(group, issue, num_confirms): 523 526 fields = [ 524 527 group.id, 525 528 group.name, 526 'unsubmitted', 529 group.group_status.slug, 530 issue, 527 531 num_confirms, 528 532 group.officer_email, … … 531 535 output.writerow(fields) 532 536 537 q_present = Q(id__in=group_updates.values('group')) 538 missing_groups = check_groups.filter(~q_present) 539 #print len(list(group_updates)) 540 for group in missing_groups: 541 #num_confirms = len(people_confirmations.filter(groups=group)) 542 output_issue(group, 'unsubmitted', '') 543 533 544 for group_update in group_updates: 534 545 group = group_update.group 535 num_confirms = len(people_confirmations.filter(groups=group))546 num_confirms = people_confirmations.filter(groups=group).count() 536 547 problems = [] 537 548 … … 545 556 546 557 for problem in problems: 547 fields = [ 548 group.id, 549 group.name, 550 problem, 551 num_confirms, 552 group.officer_email, 553 ] 554 if account_numbers: fields.append(group.main_account_id) 555 output.writerow(fields) 556 558 output_issue(group, problem, num_confirms) 557 559 558 560 return HttpResponse(buf.getvalue(), mimetype='text/csv', ) 559 561 560 562 563 class PeopleStatusLookupForm(ModelForm): 564 class Meta: 565 model = forms.models.PeopleStatusLookup 566 fields = ('people', ) 567 568 def people_status_lookup(request, pk=None, ): 569 if pk is None: 570 if request.method == 'POST': 571 form = PeopleStatusLookupForm(request.POST, request.FILES, ) 572 if form.is_valid(): # All validation rules pass 573 lookup = form.save(commit=False) 574 lookup.requestor = request.user 575 lookup.referer = request.META['HTTP_REFERER'] 576 lookup.update_classified_people() 577 results = lookup.classifications_with_descriptions() 578 lookup.save() 579 else: 580 form = PeopleStatusLookupForm() 581 results = None 582 else: 583 if request.user.has_perm('forms.view_peoplestatusupdate'): 584 lookup = get_object_or_404(forms.models.PeopleStatusLookup, pk=int(pk)) 585 results = lookup.classifications_with_descriptions() 586 form = None 587 else: 588 raise PermissionDenied("You don't have permission to view old lookup requests.") 589 590 context = { 591 'form': form, 592 'results': results, 593 } 594 595 return render_to_response('membership/people-lookup.html', context, context_instance=RequestContext(request), ) 561 596 562 597 ########## -
asadb/groups/models.py
r00ec3e4 r7431d13 1 import collections 1 2 import datetime 2 3 import filecmp … … 14 15 from django.db.models import Q 15 16 from django.core.validators import RegexValidator 16 from django.contrib.auth.models import User 17 from django.contrib.auth.models import User, Permission 18 from django.contrib.contenttypes.models import ContentType 17 19 from django.template.defaultfilters import slugify 18 20 … … 112 114 current_officers = OfficeHolder.current_holders.filter(person=username) 113 115 users_groups = Group.objects.filter(officeholder__in=current_officers).distinct() 116 117 @staticmethod 118 def admin_groups(username, codename='admin_group'): 119 holders = OfficeHolder.current_holders.filter_perm(codename=codename).filter(person=username) 120 users_groups = Group.objects.filter(officeholder__in=holders).distinct() 114 121 return users_groups 115 122 … … 395 402 396 403 @classmethod 404 def getRolesGrantingPerm(cls, perm=None, model=Group, codename=None, ): 405 """Get all OfficerRole objects granting a permission 406 407 Either `perm` or `codename` must be supplied, but not both. If 408 `codename` is provided (and `perm` is None), then `perm` the 409 permission corresponding to `model` (default: `Group`) and `codename` 410 will be found and used.""" 411 412 if perm is None: 413 ct = ContentType.objects.get_for_model(model) 414 print ct 415 print Permission.objects.filter(content_type=ct) 416 perm = Permission.objects.get(content_type=ct, codename=codename) 417 418 Q_user = Q(user_permissions=perm) 419 Q_group = Q(groups__permissions=perm) 420 users = User.objects.filter(Q_user|Q_group) 421 roles = cls.objects.filter(grant_user__in=users) 422 return roles 423 424 @classmethod 397 425 def retrieve(cls, slug, ): 398 426 return cls.objects.get(slug=slug) 427 399 428 reversion.register(OfficerRole) 400 429 … … 407 436 ) 408 437 438 def filter_perm(self, perm=None, model=Group, codename=None, ): 439 roles = OfficerRole.getRolesGrantingPerm(perm=perm, model=model, codename=codename) 440 return self.get_query_set().filter(role__in=roles) 441 409 442 class OfficeHolder(models.Model): 410 443 EXPIRE_OFFSET = datetime.timedelta(seconds=1) … … 433 466 def __repr__(self, ): 434 467 return str(self) 468 435 469 reversion.register(OfficeHolder) 436 470 -
asadb/template/base.html
r35280b4 r5560f6d 7 7 <link rel="stylesheet" type="text/css" href="{{ MEDIA_URL }}style/style.css" /> 8 8 <link rel="stylesheet" type="text/css" href="{{ MEDIA_URL }}style/page-frame.css" /> 9 {% block extrahead %} 10 {% endblock %} 9 11 10 12 </head> -
asadb/template/fysm/fysm_listing.html
r8948cef r21ab6b3 12 12 <p>Hello incoming MIT students!</p> 13 13 14 <p>Student activities play an important role in student life at MIT & mdash; they're a14 <p>Student activities play an important role in student life at MIT – they're a 15 15 great place to meet people, practice old skills and learn new ones, have fun, 16 16 and give back to the community. Undergraduate and graduate students, along -
asadb/template/groups/group_change_officers.html
r53e624e r21ab6b3 56 56 <p>Please note:</p> 57 57 <ul> 58 <li>We don't track "group membership" & mdash; people will show up in the list below only if they have one of the roles listed</li>59 <li>Type only the <em>Athena username</em> to add people & mdash; do not type full names or names plus username</li>58 <li>We don't track "group membership" – people will show up in the list below only if they have one of the roles listed</li> 59 <li>Type only the <em>Athena username</em> to add people – do not type full names or names plus username</li> 60 60 <li>To add <em>more than four</em> new people, add four at a time and <em>submit multiple times</em></li> 61 61 </ul> -
asadb/template/membership/admin.html
rd6f8984 r21ab6b3 1 1 {% extends "base.html" %} 2 2 3 {% block title %}Membership confirmations & mdash; ASA Exec pages{% endblock %}3 {% block title %}Membership confirmations – ASA Exec pages{% endblock %} 4 4 {% block content %} 5 5 6 <h2>Membership confirmations & mdash; ASA Exec pages</h2>6 <h2>Membership confirmations – ASA Exec pages</h2> 7 7 8 <p>Exec members can check the <a href='{% url membership-issues %}'>list of groups with issues</a> (or a version <a href='{% url membership-issues %}?accounts=1'>with account numbers</a>)</p> 8 <p>Exec members can check the issues:</p> 9 10 <table class='pretty-table'> 11 <tr> 12 <th>Name</th> 13 <th>Create date</th> 14 <th>Issues</th> 15 <th>(with accounts)</th> 16 </tr> 17 {% for cycle in cycle_list %} 18 <tr> 19 <th>{{cycle.name}}</th> 20 <td>{{cycle.create_date}}</td> 21 <td><a href='{% url membership-issues cycle.slug %}'>Issues</a></td> 22 <td><a href='{% url membership-issues cycle.slug %}?accounts=1'>(with accounts)</a></td> 23 </tr> 24 {% endfor %} 25 </table> 9 26 10 27 <p>The list includes the following types of issues:</p> 11 28 <dl> 12 <dt>unsubmitted</dt><dd>active groups ("group status" is "Active") who have not submitted an update (ever — see ASA-#191)</dd>13 <dt>confirmations</dt><dd>groups that have submitted an update (ever) but had less than five members confirm membership (again, ever — ASA-#191)</dd>14 <dt>50%</dt><dd>groups that (ever)submitted a confirmation with more non-students (alum, other affiliates, or other) than students (grad or undergrad)</dd>29 <dt>unsubmitted</dt><dd>active or suspended groups who have not submitted an update 30 <dt>confirmations</dt><dd>groups that have submitted an update but had less than five members confirm membership</dd> 31 <dt>50%</dt><dd>groups that submitted a confirmation with more non-students (alum, other affiliates, or other) than students (grad or undergrad)</dd> 15 32 </dl> 16 33 -
asadb/template/membership/confirm.html
r11941e1 r5560f6d 1 1 {% extends "base.html" %} 2 3 {% block extrahead %} 4 <link rel="stylesheet" href="{{MEDIA_URL}}js/libs/chosen/chosen.css"> 5 {% endblock %} 2 6 3 7 {% block title %}Membership update{% endblock %} … … 77 81 </table> 78 82 79 <h3>Option 2: Add or remove groups by searching</h3>83 <h3>Option 2: Select all your groups at once</h3> 80 84 81 <form action="" method="get"> 82 <table class='pretty-table'> 83 {{ filter.form.as_table }} 84 </table> 85 <input type="submit" name='search' value="Search" /> 86 <input type="submit" name='stop-search' value="Stop searching" /> 87 </form> 88 89 {% if show_filtered_groups %} 90 <table class='pretty-table'> 91 <thead> 92 <tr> 93 <th>Name</th> 94 <th>Website</th> 95 <th>ASA DB</th> 96 <th>Description</th> 97 <th>Add/Remove</th> 98 </tr> 99 </thead> 100 <tbody> 101 {% for group in filtered_groups %} 102 <tr> 103 <th>{{group.name}}</th> 104 <td>{% if group.website_url %}<a href='{{group.website_url}}'>Website</a>{%endif%}</td> 105 <td><a href='{% url groups:group-detail group.pk %}'>DB Entry</a></td> 106 <td>{{group.description}}</td> 107 <td> 108 <form action="" method="post"> 109 {% csrf_token %} 110 <input type="hidden" name="group" value="{{group.pk}}"> 111 {% if group in member_groups %} 112 <input type="hidden" name="action" value="remove"> 113 <input type="submit" name="add-remove" value="Remove"> 114 {% else %} 115 <input type="hidden" name="action" value="add"> 116 <input type="submit" name="add-remove" value="Add"> 117 {% endif %} 118 </form> 119 </td> 120 </tr> 121 {% endfor %} 122 </tbody> 123 </table> 124 {% else %} 125 <p>Hit "search" to see matching groups.</p> 126 {% endif %} 127 128 129 <h3>Option 3: Select all your groups at once</h3> 130 131 <p>Below is a list of all recognized groups. You can go through picking out the groups you are a member of. However, you should be careful not to deselect any groups (unless you aren't a member of them, of course).</p> 85 <p>Below, you can add or remove any recognized group from the list of groups you are a member of.</p> 132 86 133 87 <form enctype="multipart/form-data" method="post" action=""> … … 139 93 </form> 140 94 95 96 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js" type="text/javascript"></script> 97 <script src="{{MEDIA_URL}}js/libs/chosen/chosen.jquery.js" type="text/javascript"></script> 98 <script type="text/javascript"> 99 $("#id_groups").chosen(); 100 </script> 101 141 102 {% endblock %} -
asadb/template/membership/thanks.html
r1ed7e51 r21ab6b3 1 1 {% extends "base.html" %} 2 2 3 {% block title %}Membership update & mdash; thanks{% endblock %}3 {% block title %}Membership update – thanks{% endblock %} 4 4 {% block content %} 5 5 6 <h2>Membership update & mdash; thanks</h2>6 <h2>Membership update – thanks</h2> 7 7 8 8 <p>Thanks for confirming your group's activity. You should receive a confirmation email to your officer's list, and a copy of the anti-hazing law to your group list.</p> -
asadb/template/membership/update.html
r6e247d3 r3d2db0b 5 5 6 6 7 <h1>ASA Group Registration & Anti-Hazing Form </h1>7 <h1>ASA Group Registration & Anti-Hazing Form for <a href='{%url groups:group-detail group.pk%}'>{{group.name}}</a></h1> 8 8 9 9 <p>The purpose of this electronic registration is for the ASA to determine which groups are still active and which are not. There are four components to this process:</p> … … 35 35 <h3><a name='components-membership'></a>3. Providing Membership Information</h3> 36 36 37 <p>We are requiring that groups provide membership information & mdash; both membership numbers and a membership list. This information is important for our understanding of your group and ensuring that groups are meeting our membership standards. We will also share the membership numbers with the funding boards (GSC, UA, and LEF/ARCADE) for groups that apply to those sources. <strong>It is very important you are honest when answering these questions</strong>, even if you are concerned your membership does not meet our standards. We will provide time and support for groups to improve their student participation as needed — both in terms of number and proportion of students. Groups that are shown to be dishonest in this process, particularly with regards to meeting our standards, <strong>may have funding and space eligibility revoked or be suspended or derecognized</strong>.</p>37 <p>We are requiring that groups provide membership information – both membership definition and the corresponding numbers. This information is important for our understanding of your group and ensuring that groups are meeting our membership standards. We will also share the membership numbers with the funding boards (GSC, UA, and LEF/ARCADE) for groups that apply to those sources. <strong>It is very important you are honest when answering these questions</strong>, even if you are concerned your membership does not meet our standards. We will provide time and support for groups to improve their student participation as needed – both in terms of number and proportion of students. Groups that are shown to be dishonest in this process, particularly with regards to meeting our standards, <strong>may have funding and space eligibility revoked or be suspended or derecognized</strong>.</p> 38 38 39 39 <dl> 40 <dt>Minimum definition of member</dt><dd><p>For the purposes of this form, the minimum definition of membership you should use is people you would expect to confirm membership in your group (not that they all have to) and people that you consider to be regular or active members of your group. (You may be more stringent, based on how your group views or defines membership internally.) You must state the specific definition of membership you are using below. This does not need to be a membership definition that is in your constitution.</p></dd>40 <dt>Minimum definition of member</dt><dd><p>For the purposes of this form, the minimum definition of membership you use should include only people who (a) you would expect to confirm membership in your group (not that they all have to) if asked and (b) you consider to be regular or active members of your group. Members should satisfy both (a) and (b); you should not count members who satisfy only one or the other. (You may be more stringent, based on how your group views or defines membership internally.) You must state the specific definition of membership you are using below. This does not need to be a membership definition that is in your constitution.</p></dd> 41 41 42 <dt>Privacy</dt><dd><p>The list of members you provide will not be shared. If we need to contact them we will contact your officer/exec list first — this would only be if we have concerns about the information provided or to spot-check the information provided. If feasible, we will ask your officer/exec list to contact your members directly.</p></dd> 43 44 <dt>Recruitment</dt><dd><p>If you are still in the midst of or leading up to your major recruitment period, we encourage you to submit current numbers and a list soon to ensure you have something submitted before the deadline. Then you can submit an updated form later, either before or after the deadline. You don't need to do this if your membership changes slightly, but we recommend you do so if your numbers change significantly.</p></dd> 42 <dt>Recruitment</dt><dd><p>If you are still in the midst of or leading up to your major recruitment period, we encourage you to submit current numbers soon to ensure you have something submitted before the deadline. Then you can submit an updated form later, either before or after the deadline. You don't need to do this if your membership changes slightly, but we recommend you do so if your numbers change significantly.</p></dd> 45 43 46 44 </dl> -
asadb/urls.py
r3c1b20b r88a856b 65 65 ), 66 66 url(r'^membership/submitted/$', forms.views.View_GroupMembershipList.as_view(), name='membership-submitted', ), 67 url( 68 r'^membership/admin/$', 69 'django.views.generic.simple.direct_to_template', 70 {'template': 'membership/admin.html', 'extra_context': { 'pagename':'groups' }, }, 71 name='membership-admin', 72 ), 73 url(r'^membership/admin/issues.csv$', forms.views.group_confirmation_issues, name='membership-issues', ), 67 url(r'^membership/admin/$', forms.views.View_GroupConfirmationCyclesList.as_view(), name='membership-admin', ), 68 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', ), 74 70 75 71 # Midway -
asadb/groups/views.py
r89165c1 r7dde669 696 696 from_email='asa-admin@mit.edu', 697 697 ) 698 # XXX: Handle this better699 if officer_domain != 'mit.edu' or (create_group_list and group_domain != 'mit.edu'):700 accounts_mail.to = ['asa-groups@mit.edu']701 accounts_mail.cc = ['asa-db@mit.edu']702 accounts_mail.subject = "ERROR: " + accounts_mail.subject703 accounts_mail.body = "Bad domain on officer or group list\n\n" + accounts_mail.body704 698 705 699 else: … … 828 822 return render_to_response('groups/create/startup.html', context, context_instance=RequestContext(request), ) 829 823 824 def review_group_check_warnings(group_startup, group, ): 825 warnings = [] 826 827 if group.name.startswith("MIT "): 828 warnings.append('Group name starts with "MIT". Generally, we prefer "Foo, MIT" instead.') 829 if "mit" in group.athena_locker.lower(): 830 warnings.append('Athena locker name contains "mit", which may be redundant with paths like "http://web.mit.edu/mitfoo" or "/mit/foo/".') 831 832 if group_startup.president_kerberos == group_startup.treasurer_kerberos: 833 warnings.append('President matches Treasurer.') 834 if "%s@mit.edu" % (group_startup.president_kerberos, ) in (group.officer_email, group.group_email): 835 warnings.append('President email matches officer and/or group email.') 836 if group.officer_email == group.group_email: 837 warnings.append('Officer email matches group email.') 838 839 if '@mit.edu' not in group.officer_email or '@mit.edu' not in group.group_email: 840 warnings.append('Officer and/or group email are non-MIT. Ensure that they are not requesting the addresses be created, and consider suggesting they use an MIT list instead.') 841 842 if '.' in group.athena_locker: 843 warnings.append('Athena locker contains a ".". This is not compatible with scripts.mit.edu\'s wildcard certificate, and may cause other problems.') 844 if '_' in group.athena_locker: 845 warnings.append('Athena locker contains a "_". If this locker name gets used in a URL (for example, locker.scripts.mit.edu), it will technically violate the hostname specification and may not work in some clients.') 846 if len(group.athena_locker) > 12: 847 warnings.append('Athena locker is more than twelve characters long. In general, twelve characters is the longest Athena locker an ASA-recognized group can get.') 848 849 return warnings 850 830 851 @permission_required('groups.recognize_group') 831 852 def recognize_normal_group(request, pk, ): … … 843 864 if group_startup.stage != groups.models.GROUP_STARTUP_STAGE_SUBMITTED: 844 865 return render_to_response('groups/create/err.not-applying.html', context, context_instance=RequestContext(request), ) 866 867 context['warnings'] = review_group_check_warnings(group_startup, group) 845 868 846 869 context['msg'] = "" -
asadb/template/groups/create/startup_review.html
r172255b r7dde669 51 51 {% endif %} 52 52 53 {% if warnings %} 54 <div class='messagebox warnbox'> 55 <h3>Potential issues</h3> 56 57 <p>The following potential issues were identified with this group's startup application:</p> 58 59 <ul> 60 {% for warning in warnings %} 61 <li>{{warning}}</li> 62 {%endfor%} 63 </ul> 64 65 <p>Please look over these issues. Usually, you should <strong>reach out to the group</strong> and ask them to fix (or consider fixing) each issue before you approve the group. In some cases, it may be appropriate to ignore an issue. (For example, "MIT" is a central part of some group's acronyms (like "HTGAMIT"). In these cases, confirming with the group may not be necessary.)</p> 66 </div> 67 {%endif%} 68 53 69 {% if disp_form %} 54 70 <form enctype="multipart/form-data" method="post" action=""> 55 71 {% csrf_token %} 72 {% if warnings %} 73 <input type='submit' name='approve' value='Approve DESPITE WARNINGS' /> 74 {% else %} 56 75 <input type='submit' name='approve' value='Approve' /> 76 {% endif %} 57 77 <input type='submit' name='reject' value='Reject' /> 58 78 </form>
Note: See TracChangeset
for help on using the changeset viewer.