341 lines
15 KiB
Python
341 lines
15 KiB
Python
# Copyright The IETF Trust 2007, All Rights Reserved
|
|
|
|
from forms import NonWgStep1, ListReqStep1, PickApprover, DeletionPickApprover, UrlMultiWidget, Preview, ListReqAuthorized, ListReqClose, MultiEmailField, AdminRequestor, ApprovalComment, ListApprover
|
|
from models import NonWgMailingList, MailingList, Domain
|
|
from ietf.idtracker.models import Area, PersonOrOrgInfo, AreaDirector, WGChair
|
|
from django import newforms as forms
|
|
from django.shortcuts import get_object_or_404, render_to_response
|
|
from django.template import RequestContext
|
|
from django.db.models import Q
|
|
from django.contrib.sites.models import Site
|
|
from ietf.contrib import wizard, form_decorator
|
|
from ietf.utils.mail import send_mail_subj
|
|
from datetime import datetime
|
|
|
|
def formchoice(form, field):
|
|
if not(form.is_valid()):
|
|
return None
|
|
d = str(form.clean_data[field])
|
|
for k, v in form.fields[field].choices:
|
|
if str(k) == d:
|
|
return v
|
|
# oddly, one of the forms stores the translated value
|
|
# in clean_data; the other stores the key. This second
|
|
# if wouldn't be needed if both stored the key.
|
|
# This whole function wouldn't be needed if both stored
|
|
# the value.
|
|
if str(v) == d:
|
|
return v
|
|
return None
|
|
|
|
nonwg_fields = {
|
|
'id': None,
|
|
'status': None,
|
|
'ds_name': None,
|
|
'ds_email': None,
|
|
'msg_to_ad': None,
|
|
#'admin': MultiEmailField(label='List Administrator(s)', widget=forms.Textarea(attrs={'rows': 3, 'cols': 50})),
|
|
}
|
|
|
|
nonwg_attrs = {
|
|
's_name': {'size': 50},
|
|
's_email': {'size': 50},
|
|
'list_name': {'size': 80},
|
|
}
|
|
|
|
nonwg_widgets = {
|
|
'list_url': UrlMultiWidget(choices=(('http://', 'http://'), ('https://', 'https://'), ('mailto:', 'mailto:')), attrs = {'size': 50}),
|
|
'admin': forms.Textarea(attrs = {'rows': 3, 'cols': 50}),
|
|
'purpose': forms.Textarea(attrs = {'rows': 4, 'cols': 70}),
|
|
'subscribe_url': UrlMultiWidget(choices=(('n/a', 'Not Applicable'), ('http://', 'http://'), ('https://', 'https://')), attrs = {'size': 50}),
|
|
'subscribe_other': forms.Textarea(attrs = {'rows': 3, 'cols': 50}),
|
|
}
|
|
|
|
nonwg_querysets = {
|
|
'area': Area.objects.filter(status=1)
|
|
}
|
|
|
|
nonwg_callback = form_decorator(fields=nonwg_fields, widgets=nonwg_widgets, attrs=nonwg_attrs, querysets=nonwg_querysets)
|
|
|
|
def gen_approval(approvers, parent):
|
|
class BoundApproval(parent):
|
|
_approvers = approvers
|
|
def __init__(self, *args, **kwargs):
|
|
super(BoundApproval, self).__init__(self._approvers, *args, **kwargs)
|
|
return BoundApproval
|
|
|
|
class NonWgWizard(wizard.Wizard):
|
|
clean_forms = []
|
|
def get_template(self):
|
|
templates = []
|
|
if self.step > 0:
|
|
action = {'add': 'addedit', 'edit': 'addedit', 'delete': 'delete'}[self.clean_forms[0].clean_data['add_edit']]
|
|
templates.append("mailinglists/nwg_wizard_%s_step%d.html" % (action, self.step))
|
|
templates.append("mailinglists/nwg_wizard_%s.html" % (action))
|
|
templates.append("mailinglists/nwg_wizard_step%d.html" % (self.step))
|
|
templates.append("mailinglists/nwg_wizard.html")
|
|
return templates
|
|
def render_template(self, *args, **kwargs):
|
|
self.extra_context['clean_forms'] = self.clean_forms
|
|
if self.step == 3:
|
|
form0 = self.clean_forms[0]
|
|
add_edit = form0.clean_data['add_edit']
|
|
if add_edit == 'add' or add_edit == 'edit':
|
|
# Can't get the choice mapping directly from the form
|
|
self.extra_context['area'] = formchoice(self.clean_forms[1], 'area')
|
|
self.extra_context['approver'] = formchoice(self.clean_forms[2], 'approver')
|
|
if self.step == 2:
|
|
form0 = self.clean_forms[0]
|
|
add_edit = form0.clean_data['add_edit']
|
|
if add_edit == 'delete':
|
|
self.extra_context['list_q'] = NonWgMailingList.objects.get(pk=self.clean_forms[0].clean_data['list_id_delete'])
|
|
self.extra_context['approver'] = formchoice(self.clean_forms[1], 'approver')
|
|
return super(NonWgWizard, self).render_template(*args, **kwargs)
|
|
def failed_hash(self, step):
|
|
raise NotImplementedError("step %d hash failed" % step)
|
|
def process_step(self, request, form, step):
|
|
form.full_clean()
|
|
if step == 0:
|
|
self.clean_forms = [ form ]
|
|
if form.clean_data['add_edit'] == 'add':
|
|
self.form_list.append(forms.form_for_model(NonWgMailingList, formfield_callback=nonwg_callback))
|
|
elif form.clean_data['add_edit'] == 'edit':
|
|
self.form_list.append(forms.form_for_instance(NonWgMailingList.objects.get(pk=form.clean_data['list_id']), formfield_callback=nonwg_callback))
|
|
elif form.clean_data['add_edit'] == 'delete':
|
|
list = NonWgMailingList.objects.get(pk=form.clean_data['list_id_delete'])
|
|
self.form_list.append(gen_approval([ad.person_id for ad in list.area.areadirector_set.all()], DeletionPickApprover))
|
|
self.form_list.append(Preview)
|
|
else:
|
|
self.clean_forms.append(form)
|
|
if step == 1:
|
|
form0 = self.clean_forms[0]
|
|
add_edit = form0.clean_data['add_edit']
|
|
if add_edit == 'add' or add_edit == 'edit':
|
|
self.form_list.append(gen_approval([ad.person_id for ad in Area.objects.get(area_acronym=form.clean_data['area']).areadirector_set.all()], PickApprover))
|
|
self.form_list.append(Preview)
|
|
super(NonWgWizard, self).process_step(request, form, step)
|
|
def done(self, request, form_list):
|
|
add_edit = self.clean_forms[0].clean_data['add_edit']
|
|
list = None
|
|
old = None
|
|
if add_edit == 'add' or add_edit == 'edit':
|
|
template = 'mailinglists/nwg_addedit_email.txt'
|
|
approver = self.clean_forms[2].clean_data['approver']
|
|
list = NonWgMailingList(**self.clean_forms[1].clean_data)
|
|
list.__dict__.update(self.clean_forms[2].clean_data)
|
|
list.id = None # create a new row no matter what
|
|
list.status = 0
|
|
if add_edit == 'edit':
|
|
old = NonWgMailingList.objects.get(pk=self.clean_forms[0].clean_data['list_id'])
|
|
else:
|
|
template = 'mailinglists/nwg_delete_email.txt'
|
|
approver = self.clean_forms[1].clean_data['approver']
|
|
list = NonWgMailingList.objects.get(pk=self.clean_forms[0].clean_data['list_id_delete'])
|
|
list.__dict__.update(self.clean_forms[1].clean_data)
|
|
list.status = 1
|
|
list.save()
|
|
approver_email = PersonOrOrgInfo.objects.get(pk=approver).email()
|
|
approver_name = PersonOrOrgInfo.objects.get(pk=approver)
|
|
send_mail_subj(request, [ approver_email ], None, 'mailinglists/nwg_wizard_subject.txt', 'mailinglists/nwg_wizard_done_email.txt', {'add_edit': add_edit, 'old': old, 'list': list, 'forms': self.clean_forms})
|
|
return render_to_response( 'mailinglists/nwg_wizard_done.html', {'approver': approver_name, 'add_edit': add_edit, 'old': old, 'list': list, 'forms': self.clean_forms}, context_instance=RequestContext(request) )
|
|
|
|
def non_wg_wizard(request):
|
|
wiz = NonWgWizard([ NonWgStep1 ])
|
|
return wiz(request)
|
|
|
|
list_fields = {
|
|
'mailing_list_id': None,
|
|
'request_date': None,
|
|
'auth_person': None,
|
|
'approved': None,
|
|
'approved_date': None,
|
|
'reason_to_delete': None,
|
|
'add_comment': None,
|
|
'mail_type': None,
|
|
'mail_cat': None,
|
|
'admins': MultiEmailField(label='List Administrator(s)', widget=AdminRequestor(attrs={'cols': 41, 'rows': 4})),
|
|
'initial_members': MultiEmailField(label='Initial list member(s)', widget=forms.Textarea(attrs={'cols': 41, 'rows': 4}), required=False),
|
|
}
|
|
|
|
list_labels = {
|
|
'post_who': 'Who is allowed to post to this list?',
|
|
}
|
|
|
|
# would like something to display @domain after the email list name?
|
|
list_widgets = {
|
|
'subscription': forms.Select(choices=MailingList.SUBSCRIPTION_CHOICES),
|
|
'post_who': forms.Select(choices=(('1', 'List members only'), ('0', 'Open'))),
|
|
'post_admin': forms.Select(choices=(('0', 'No'), ('1', 'Yes'))),
|
|
'archive_private': forms.Select(choices=(('0', 'No'), ('1', 'Yes'))),
|
|
'domain_name': forms.HiddenInput(),
|
|
}
|
|
|
|
list_attrs = {
|
|
'requestor': { 'size': 55 },
|
|
'requestor_email': { 'size': 55 },
|
|
'mlist_name': { 'size': 10 },
|
|
'short_desc': { 'size': 55 },
|
|
'long_desc': { 'cols': 41, 'rows': 4, 'wrap': 'virtual' },
|
|
'admins': { 'cols': 41, 'rows': 4 },
|
|
'initial_members': { 'cols': 41, 'rows': 4 },
|
|
'welcome_message': { 'cols': 41, 'rows': 4 },
|
|
'welcome_new': { 'cols': 41, 'rows': 4 },
|
|
'archive_remote': { 'cols': 41, 'rows': 4 },
|
|
}
|
|
|
|
list_callback = form_decorator(fields=list_fields, widgets=list_widgets, attrs=list_attrs)
|
|
|
|
def gen_list_approval(approvers, requestor, parent):
|
|
class ListApproval(parent):
|
|
_approvers = approvers
|
|
_requestor = requestor
|
|
def __init__(self, *args, **kwargs):
|
|
super(ListApproval, self).__init__(self._approvers, self._requestor, *args, **kwargs)
|
|
return ListApproval
|
|
|
|
class ListReqWizard(wizard.Wizard):
|
|
clean_forms = []
|
|
main_step = 1
|
|
requestor_is_approver = False
|
|
mlist_known = True
|
|
def get_template(self):
|
|
'''Start with form class, then step number, then the base form.'''
|
|
templates = []
|
|
c = self.form_list[self.step].__name__
|
|
templates.append("mailinglists/list_wizard_%s.html" % (c))
|
|
templates.append("mailinglists/list_wizard_step%d.html" % (self.step))
|
|
templates.append("mailinglists/list_wizard.html")
|
|
return templates
|
|
def render_template(self, *args, **kwargs):
|
|
self.extra_context['mlist_known'] = self.mlist_known
|
|
if self.step > 0:
|
|
self.extra_context['form0'] = self.clean_forms[0]
|
|
if self.clean_forms[0]['mail_type'].data.startswith('close'):
|
|
self.extra_context['req'] = 'delete'
|
|
else:
|
|
self.extra_context['req'] = 'add'
|
|
if self.step > self.main_step:
|
|
self.extra_context['main_form'] = self.clean_forms[self.main_step]
|
|
self.extra_context['requestor_is_approver'] = self.requestor_is_approver
|
|
if self.step == self.main_step + 1:
|
|
self.extra_context['list'] = self.getlist()
|
|
return super(ListReqWizard, self).render_template(*args, **kwargs)
|
|
def parse_params(self, request, *args, **kwargs):
|
|
super(ListReqWizard, self).parse_params(request, *args, **kwargs)
|
|
if self.step == 0:
|
|
# allow javascript "redirects" to set initial values
|
|
self.initial[0] = request.GET
|
|
def process_step(self, request, form, step):
|
|
form.full_clean()
|
|
if step == 0:
|
|
self.clean_forms = [ form ]
|
|
else:
|
|
self.clean_forms.append(form)
|
|
form0 = self.clean_forms[0]
|
|
needs_auth = form0.clean_data['mail_type'].endswith('non') and form0.clean_data['domain_name'] != 'ietf.org'
|
|
if step == 0:
|
|
self.main_step = 1
|
|
if needs_auth:
|
|
self.form_list.append(ListReqAuthorized)
|
|
self.main_step = 2
|
|
if form.clean_data['mail_type'].startswith('close'):
|
|
self.form_list.append(ListReqClose)
|
|
if form.clean_data['mail_type'] == 'closewg':
|
|
self.initial[self.main_step] = {'mlist_name': form.clean_data['group']}
|
|
else:
|
|
self.initial[self.main_step] = {'mlist_name': form.clean_data['list_to_close']}
|
|
else:
|
|
self.form_list.append(forms.form_for_model(MailingList, formfield_callback=list_callback))
|
|
if form.clean_data['mail_type'].endswith('wg'):
|
|
self.initial[self.main_step] = {'mlist_name': form.clean_data['group']}
|
|
else:
|
|
self.initial[self.main_step] = {}
|
|
self.mlist_known = False
|
|
if form.clean_data['mail_type'].endswith('wg'):
|
|
self.initial[self.main_step].update({'domain_name': 'ietf.org'})
|
|
else:
|
|
self.initial[self.main_step].update({'domain_name': form.clean_data['domain_name']})
|
|
if step == self.main_step:
|
|
approvers = mlist_approvers(form0.clean_data['mail_type'], form.clean_data['domain_name'], form0.clean_data['group'])
|
|
requestor_email = form.clean_data['requestor_email']
|
|
requestor_person = None
|
|
for a in approvers:
|
|
if requestor_email == a.person.email()[1]:
|
|
requestor_person = a
|
|
self.requestor_is_approver = True
|
|
self.form_list.append(gen_list_approval(approvers, requestor_person, ListApprover))
|
|
super(ListReqWizard, self).process_step(request, form, step)
|
|
def getlist(self):
|
|
list = MailingList(**self.clean_forms[self.main_step].clean_data)
|
|
list.mailing_list_id = None # make sure that we create a new row
|
|
list.mail_type = MailingList.MAILTYPE_MAP[self.clean_forms[0].clean_data['mail_type']]
|
|
list.approved = 0
|
|
return list
|
|
def done(self, request, form_list):
|
|
list = self.getlist()
|
|
list.auth_person_id = int(self.clean_forms[self.main_step + 1].clean_data['approver'])
|
|
list.save()
|
|
approver_email = list.auth_person.email()
|
|
site = Site.objects.get_current()
|
|
if list.mail_type == 5 or list.mail_type == 6:
|
|
req = 'delete'
|
|
else:
|
|
req = 'add'
|
|
send_mail_subj(request, [ approver_email ], None, 'mailinglists/list_wizard_subject.txt', 'mailinglists/list_wizard_done_email.txt', {'list': list, 'forms': self.clean_forms, 'requestor_is_approver': self.requestor_is_approver, 'site': site, 'req': req})
|
|
return render_to_response('mailinglists/list_wizard_done.html', {'list': list, 'forms': self.clean_forms, 'requestor_is_approver': self.requestor_is_approver, 'req': req}, context_instance=RequestContext(request) )
|
|
|
|
def mlist_approvers(mail_type, domain_name, group):
|
|
approvers = []
|
|
if domain_name == 'ietf.org':
|
|
approvers += AreaDirector.objects.filter(area__status=Area.ACTIVE)
|
|
if mail_type == 'movewg':
|
|
approvers += WGChair.objects.filter(group_acronym=group)
|
|
if mail_type.endswith('non'):
|
|
domain = Domain.objects.get(domain=domain_name)
|
|
approvers += domain.approvers.all()
|
|
return approvers
|
|
|
|
def list_req_wizard(request):
|
|
wiz = ListReqWizard([ ListReqStep1 ])
|
|
return wiz(request)
|
|
|
|
def list_req_help(request, field):
|
|
return render_to_response('mailinglists/list_help_%s.html' % field, {},
|
|
context_instance=RequestContext(request) )
|
|
|
|
def list_approve(request, object_id):
|
|
list = get_object_or_404(MailingList, mailing_list_id=object_id)
|
|
if list.mail_type == 5 or list.mail_type == 6:
|
|
req = 'delete'
|
|
else:
|
|
req = 'add'
|
|
action = 'toapprove'
|
|
email_to = None
|
|
if request.method == 'POST':
|
|
if request.POST.has_key('approved'):
|
|
list.approved=1
|
|
list.approved_date = datetime.now()
|
|
list.add_comment = request.POST['add_comment']
|
|
list.save()
|
|
if list.mail_type == 6: # deletion of non-wg list
|
|
for nonwg in NonWgMailingList.objects.filter(Q(list_url__iendswith=list.mlist_name) | Q(list_url__iendswith='%s@%s' % (list.mlist_name, list.domain_name))):
|
|
nonwg.status = -1
|
|
nonwg.save()
|
|
email_to = 'ietf-action@ietf.org'
|
|
email_cc = [(list.requestor, list.requestor_email)]
|
|
action = 'approved'
|
|
elif request.POST.has_key('disapprove'):
|
|
list.approved = -1
|
|
list.approved_date = datetime.now()
|
|
list.add_comment = request.POST['add_comment']
|
|
list.save()
|
|
email_to = [(list.requestor, list.requestor_email)]
|
|
email_cc = None
|
|
action = 'denied'
|
|
if email_to is not None:
|
|
send_mail_subj(request, email_to, ('Mailing List Request Tool', 'ietf-secretariat-reply@ietf.org'), 'mailinglists/list_subject.txt', 'mailinglists/list_email.txt', {'list': list, 'action': action, 'req': req}, email_cc)
|
|
# fall through
|
|
form = ApprovalComment()
|
|
return render_to_response('mailinglists/list_%s.html' % action, {'list': list, 'form': form, 'req': req},
|
|
context_instance=RequestContext(request) )
|