367 lines
15 KiB
Python
367 lines
15 KiB
Python
# Copyright The IETF Trust 2007, All Rights Reserved
|
|
|
|
from django.conf import settings
|
|
from django.core.exceptions import ObjectDoesNotExist
|
|
from django.db import models
|
|
from django.template.loader import render_to_string
|
|
from django.contrib.auth.models import User
|
|
from django.core.urlresolvers import reverse as urlreverse
|
|
from ietf.idtracker.models import Acronym, PersonOrOrgInfo, Area, IESGLogin
|
|
from ietf.liaisons.mail import IETFEmailMessage
|
|
from ietf.ietfauth.models import LegacyLiaisonUser
|
|
from ietf.utils.admin import admin_link
|
|
|
|
class LiaisonPurpose(models.Model):
|
|
purpose_id = models.AutoField(primary_key=True)
|
|
purpose_text = models.CharField(blank=True, max_length=50)
|
|
def __str__(self):
|
|
return self.purpose_text
|
|
class Meta:
|
|
db_table = 'liaison_purpose'
|
|
|
|
class FromBodies(models.Model):
|
|
from_id = models.AutoField(primary_key=True)
|
|
body_name = models.CharField(blank=True, max_length=35)
|
|
poc = models.ForeignKey(PersonOrOrgInfo, db_column='poc', null=True)
|
|
is_liaison_manager = models.BooleanField()
|
|
other_sdo = models.BooleanField()
|
|
email_priority = models.IntegerField(null=True, blank=True)
|
|
def __str__(self):
|
|
return self.body_name
|
|
class Meta:
|
|
db_table = 'from_bodies'
|
|
verbose_name = "From body"
|
|
verbose_name_plural = "From bodies"
|
|
contact_link = admin_link('poc', label='Contact')
|
|
|
|
|
|
|
|
class OutgoingLiaisonApproval(models.Model):
|
|
approved = models.BooleanField(default=True)
|
|
approval_date = models.DateField(null=True, blank=True)
|
|
|
|
|
|
class LiaisonDetail(models.Model):
|
|
detail_id = models.AutoField(primary_key=True)
|
|
person = models.ForeignKey(PersonOrOrgInfo, null=True, db_column='person_or_org_tag')
|
|
submitted_date = models.DateField(null=True, blank=True)
|
|
last_modified_date = models.DateField(null=True, blank=True)
|
|
from_id = models.IntegerField(null=True, blank=True)
|
|
to_body = models.CharField(blank=True, null=True, max_length=255)
|
|
title = models.CharField(blank=True, null=True, max_length=255)
|
|
response_contact = models.CharField(blank=True, null=True, max_length=255)
|
|
technical_contact = models.CharField(blank=True, null=True, max_length=255)
|
|
purpose_text = models.TextField(blank=True, null=True, db_column='purpose')
|
|
body = models.TextField(blank=True,null=True)
|
|
deadline_date = models.DateField(null=True, blank=True)
|
|
cc1 = models.TextField(blank=True, null=True)
|
|
# unclear why cc2 is a CharField, but it's always
|
|
# either NULL or blank.
|
|
cc2 = models.CharField(blank=True, null=True, max_length=50)
|
|
submitter_name = models.CharField(blank=True, null=True, max_length=255)
|
|
submitter_email = models.CharField(blank=True, null=True, max_length=255)
|
|
by_secretariat = models.IntegerField(null=True, blank=True)
|
|
to_poc = models.CharField(blank=True, null=True, max_length=255)
|
|
to_email = models.CharField(blank=True, null=True, max_length=255)
|
|
purpose = models.ForeignKey(LiaisonPurpose,null=True)
|
|
replyto = models.CharField(blank=True, null=True, max_length=255)
|
|
from_raw_body = models.CharField(blank=True, null=True, max_length=255)
|
|
from_raw_code = models.CharField(blank=True, null=True, max_length=255)
|
|
to_raw_code = models.CharField(blank=True, null=True, max_length=255)
|
|
approval = models.ForeignKey(OutgoingLiaisonApproval, blank=True, null=True)
|
|
action_taken = models.BooleanField(default=False, db_column='taken_care')
|
|
related_to = models.ForeignKey('LiaisonDetail', blank=True, null=True)
|
|
def __str__(self):
|
|
return self.title or "<no title>"
|
|
def __unicode__(self):
|
|
return self.title or "<no title>"
|
|
def from_body(self):
|
|
"""The from_raw_body stores the name of the entity
|
|
sending the liaison.
|
|
For legacy liaisons (the ones with empty from_raw_body)
|
|
the legacy_from_body() is returned."""
|
|
if not self.from_raw_body:
|
|
return self.legacy_from_body()
|
|
return self.from_raw_body
|
|
def from_sdo(self):
|
|
try:
|
|
name = FromBodies.objects.get(pk=self.from_id).body_name
|
|
sdo = SDOs.objects.get(sdo_name=name)
|
|
return sdo
|
|
except ObjectDoesNotExist:
|
|
return None
|
|
def legacy_from_body(self):
|
|
"""The from_id field is a foreign key for either
|
|
FromBodies or Acronyms, depending on whether it's
|
|
the IETF or not. There is no flag field saying
|
|
which, so we just try it. If the index values
|
|
overlap, then this function will be ambiguous
|
|
and will return the value from FromBodies. Current
|
|
acronym IDs start at 925 so the day of reckoning
|
|
is not nigh."""
|
|
try:
|
|
from_body = FromBodies.objects.get(pk=self.from_id)
|
|
return from_body.body_name
|
|
except ObjectDoesNotExist:
|
|
pass
|
|
try:
|
|
acronym = Acronym.objects.get(pk=self.from_id)
|
|
try:
|
|
x = acronym.area
|
|
kind = "AREA"
|
|
except Area.DoesNotExist:
|
|
kind = "WG"
|
|
return "IETF %s %s" % (acronym.acronym.upper(), kind)
|
|
except ObjectDoesNotExist:
|
|
pass
|
|
return "<unknown body %s>" % self.from_id
|
|
def from_email(self):
|
|
"""If there is an entry in from_bodies, it has
|
|
the desired email priority. However, if it's from
|
|
an IETF WG, there is no entry in from_bodies, so
|
|
default to 1."""
|
|
try:
|
|
from_body = FromBodies.objects.get(pk=self.from_id)
|
|
email_priority = from_body.email_priority
|
|
except FromBodies.DoesNotExist:
|
|
email_priority = 1
|
|
return self.person.emailaddress_set.all().get(priority=email_priority)
|
|
def get_absolute_url(self):
|
|
return '/liaison/%d/' % self.detail_id
|
|
class Meta:
|
|
db_table = 'liaison_detail'
|
|
|
|
def notify_pending_by_email(self, fake):
|
|
from ietf.liaisons.utils import IETFHM
|
|
|
|
from_entity = IETFHM.get_entity_by_key(self.from_raw_code)
|
|
if not from_entity:
|
|
return None
|
|
to_email = []
|
|
for person in from_entity.can_approve():
|
|
to_email.append('%s <%s>' % person.email())
|
|
subject = 'New Liaison Statement, "%s" needs your approval' % (self.title)
|
|
from_email = settings.LIAISON_UNIVERSAL_FROM
|
|
body = render_to_string('liaisons/pending_liaison_mail.txt', {
|
|
'liaison': self,
|
|
'url': settings.IDTRACKER_BASE_URL + urlreverse("liaison_approval_detail", kwargs=dict(object_id=self.pk)),
|
|
'referenced_url': settings.IDTRACKER_BASE_URL + urlreverse("liaison_detail", kwargs=dict(object_id=self.related_to.pk)) if self.related_to else None,
|
|
})
|
|
mail = IETFEmailMessage(subject=subject,
|
|
to=to_email,
|
|
from_email=from_email,
|
|
body = body)
|
|
if not fake:
|
|
mail.send()
|
|
return mail
|
|
|
|
def send_by_email(self, fake=False):
|
|
if self.is_pending():
|
|
return self.notify_pending_by_email(fake)
|
|
subject = 'New Liaison Statement, "%s"' % (self.title)
|
|
from_email = settings.LIAISON_UNIVERSAL_FROM
|
|
to_email = self.to_poc.split(',')
|
|
cc = self.cc1.split(',')
|
|
if self.technical_contact:
|
|
cc += self.technical_contact.split(',')
|
|
if self.response_contact:
|
|
cc += self.response_contact.split(',')
|
|
bcc = ['statements@ietf.org']
|
|
body = render_to_string('liaisons/liaison_mail.txt', {
|
|
'liaison': self,
|
|
'url': settings.IDTRACKER_BASE_URL + urlreverse("liaison_detail", kwargs=dict(object_id=self.pk)),
|
|
'referenced_url': settings.IDTRACKER_BASE_URL + urlreverse("liaison_detail", kwargs=dict(object_id=self.related_to.pk)) if self.related_to else None,
|
|
})
|
|
mail = IETFEmailMessage(subject=subject,
|
|
to=to_email,
|
|
from_email=from_email,
|
|
cc = cc,
|
|
bcc = bcc,
|
|
body = body)
|
|
if not fake:
|
|
mail.send()
|
|
return mail
|
|
|
|
def is_pending(self):
|
|
return bool(self.approval and not self.approval.approved)
|
|
|
|
|
|
class SDOs(models.Model):
|
|
sdo_id = models.AutoField(primary_key=True, verbose_name='ID')
|
|
sdo_name = models.CharField(blank=True, max_length=255, verbose_name='SDO Name')
|
|
def __str__(self):
|
|
return self.sdo_name
|
|
def liaisonmanager(self):
|
|
try:
|
|
return self.liaisonmanagers_set.all()[0]
|
|
except:
|
|
return None
|
|
def sdo_contact(self):
|
|
try:
|
|
return self.sdoauthorizedindividual_set.all()[0]
|
|
except:
|
|
return None
|
|
class Meta:
|
|
verbose_name = 'SDO'
|
|
verbose_name_plural = 'SDOs'
|
|
db_table = 'sdos'
|
|
ordering = ('sdo_name', )
|
|
liaisonmanager_link = admin_link('liaisonmanager', label='Liaison')
|
|
sdo_contact_link = admin_link('sdo_contact')
|
|
|
|
class LiaisonStatementManager(models.Model):
|
|
person = models.ForeignKey(PersonOrOrgInfo, db_column='person_or_org_tag')
|
|
sdo = models.ForeignKey(SDOs, verbose_name='SDO')
|
|
def __unicode__(self):
|
|
return '%s (%s)' % (self.person, self.sdo)
|
|
class Meta:
|
|
abstract = True
|
|
# Helper functions, for use in the admin interface
|
|
def login_name(self):
|
|
login_name = None
|
|
try:
|
|
login_name = IESGLogin.objects.get(person=self.person).login_name
|
|
if User.objects.filter(username=login_name).count():
|
|
return login_name
|
|
except IESGLogin.DoesNotExist:
|
|
pass
|
|
try:
|
|
login_name = LegacyLiaisonUser.objects.get(person=self.person).login_name
|
|
except LegacyLiaisonUser.DoesNotExist:
|
|
pass
|
|
return login_name
|
|
def user(self):
|
|
login_name = self.login_name()
|
|
user = None
|
|
if login_name:
|
|
try:
|
|
return User.objects.get(username=login_name), login_name
|
|
except User.DoesNotExist:
|
|
pass
|
|
return None, login_name
|
|
def user_name(self):
|
|
user, login_name = self.user()
|
|
if user:
|
|
return u'<a href="/admin/auth/user/%s/">%s</a>' % (user.id, login_name)
|
|
else:
|
|
if login_name:
|
|
return u'Add login: <a href="/admin/auth/user/add/?username=%s"><span style="color: red">%s</span></a>' % (login_name, login_name)
|
|
else:
|
|
return u'Add liaison user: <a href="/admin/ietfauth/legacyliaisonuser/add/?person=%s&login_name=%s&user_level=3"><span style="color: red">%s</span></a>' % (self.person.pk, self.person.email()[1], self.person, )
|
|
|
|
user_name.allow_tags = True
|
|
def groups(self):
|
|
user, login_name = self.user()
|
|
return ", ".join([ group.name for group in user.groups.all()])
|
|
person_link = admin_link('person')
|
|
sdo_link = admin_link('sdo', label='SDO')
|
|
|
|
class LiaisonManagers(LiaisonStatementManager):
|
|
email_priority = models.IntegerField(null=True, blank=True)
|
|
def email(self):
|
|
try:
|
|
return self.person.emailaddress_set.get(priority=self.email_priority)
|
|
except ObjectDoesNotExist:
|
|
return None
|
|
class Meta:
|
|
verbose_name = 'SDO Liaison Manager'
|
|
verbose_name_plural = 'SDO Liaison Managers'
|
|
db_table = 'liaison_managers'
|
|
ordering = ('sdo__sdo_name', )
|
|
|
|
class SDOAuthorizedIndividual(LiaisonStatementManager):
|
|
class Meta:
|
|
verbose_name = 'SDO Authorized Individual'
|
|
verbose_name_plural = 'SDO Authorized Individuals'
|
|
|
|
# This table is not used by any code right now.
|
|
#class LiaisonsInterim(models.Model):
|
|
# title = models.CharField(blank=True, max_length=255)
|
|
# submitter_name = models.CharField(blank=True, max_length=255)
|
|
# submitter_email = models.CharField(blank=True, max_length=255)
|
|
# submitted_date = models.DateField(null=True, blank=True)
|
|
# from_id = models.IntegerField(null=True, blank=True)
|
|
# def __str__(self):
|
|
# return self.title
|
|
# class Meta:
|
|
# db_table = 'liaisons_interim'
|
|
|
|
class Uploads(models.Model):
|
|
file_id = models.AutoField(primary_key=True)
|
|
file_title = models.CharField(blank=True, max_length=255)
|
|
person = models.ForeignKey(PersonOrOrgInfo, db_column='person_or_org_tag')
|
|
file_extension = models.CharField(blank=True, max_length=10)
|
|
detail = models.ForeignKey(LiaisonDetail)
|
|
def __str__(self):
|
|
return self.file_title
|
|
def filename(self):
|
|
return "file%s%s" % (self.file_id, self.file_extension)
|
|
class Meta:
|
|
db_table = 'uploads'
|
|
|
|
# empty table
|
|
#class SdoChairs(models.Model):
|
|
# sdo = models.ForeignKey(SDOs)
|
|
# person = models.ForeignKey(PersonOrOrgInfo, db_column='person_or_org_tag')
|
|
# email_priority = models.IntegerField(null=True, blank=True)
|
|
# class Meta:
|
|
# db_table = 'sdo_chairs'
|
|
|
|
# changes done by convert-096.py:changed maxlength to max_length
|
|
# removed core
|
|
# removed edit_inline
|
|
# removed num_in_admin
|
|
# removed raw_id_admin
|
|
|
|
if settings.USE_DB_REDESIGN_PROXY_CLASSES or hasattr(settings, "IMPORTING_FROM_OLD_SCHEMA"):
|
|
from ietf.name.models import LiaisonStatementPurposeName
|
|
from ietf.doc.models import Document
|
|
from ietf.person.models import Email
|
|
from ietf.group.models import Group
|
|
|
|
class LiaisonStatement(models.Model):
|
|
title = models.CharField(blank=True, max_length=255)
|
|
purpose = models.ForeignKey(LiaisonStatementPurposeName)
|
|
body = models.TextField(blank=True)
|
|
deadline = models.DateField(null=True, blank=True)
|
|
|
|
related_to = models.ForeignKey('LiaisonStatement', blank=True, null=True)
|
|
|
|
from_group = models.ForeignKey(Group, related_name="liaisonstatement_from_set", null=True, blank=True, help_text="Sender group, if it exists")
|
|
from_name = models.CharField(max_length=255, help_text="Name of the sender body")
|
|
from_contact = models.ForeignKey(Email, blank=True, null=True)
|
|
to_group = models.ForeignKey(Group, related_name="liaisonstatement_to_set", null=True, blank=True, help_text="Recipient group, if it exists")
|
|
to_name = models.CharField(max_length=255, help_text="Name of the recipient body")
|
|
to_contact = models.CharField(blank=True, max_length=255, help_text="Contacts at recipient body")
|
|
|
|
reply_to = models.CharField(blank=True, max_length=255)
|
|
|
|
response_contact = models.CharField(blank=True, max_length=255)
|
|
technical_contact = models.CharField(blank=True, max_length=255)
|
|
cc = models.TextField(blank=True)
|
|
|
|
submitted = models.DateTimeField(null=True, blank=True)
|
|
modified = models.DateTimeField(null=True, blank=True)
|
|
approved = models.DateTimeField(null=True, blank=True)
|
|
|
|
action_taken = models.BooleanField(default=False)
|
|
|
|
attachments = models.ManyToManyField(Document, blank=True)
|
|
|
|
def name(self):
|
|
from django.template.defaultfilters import slugify
|
|
if self.from_group:
|
|
frm = self.from_group.acronym or self.from_group.name
|
|
else:
|
|
frm = self.from_name
|
|
if self.to_group:
|
|
to = self.to_group.acronym or self.to_group.name
|
|
else:
|
|
to = self.to_name
|
|
return slugify("liaison" + " " + self.submitted.strftime("%Y-%m-%d") + " " + frm[:50] + " " + to[:50] + " " + self.title[:115])
|
|
|
|
def __unicode__(self):
|
|
return self.title or "<no title>"
|
|
|
|
LiaisonDetailOld = LiaisonDetail
|