Skip to content

Commit 4a36338

Browse files
committed
Add proxy for LiaisonDetail, start porting the view code utils, import various liaison roles and rename a couple of fields on LiaisonStatement to try to make them more self-explanatory
- Legacy-Id: 3321
1 parent 49fb2a7 commit 4a36338

13 files changed

Lines changed: 896 additions & 65 deletions

File tree

ietf/liaisons/accounts.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from django.conf import settings
2+
13
from ietf.idtracker.models import Role, PersonOrOrgInfo
24

35

@@ -141,3 +143,6 @@ def can_edit_liaison(user, liaison):
141143
return (is_sdo_manager_for_outgoing_liaison(person, liaison) or
142144
is_sdo_manager_for_incoming_liaison(person, liaison))
143145
return False
146+
147+
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
148+
from accountsREDESIGN import *

ietf/liaisons/accountsREDESIGN.py

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
from redesign.person.models import Person
2+
from redesign.group.models import Role
3+
4+
5+
LIAISON_EDIT_GROUPS = ['Secretariat']
6+
7+
8+
def get_ietf_chair():
9+
try:
10+
return Person.objects.get(email__role__name="chair", email__role__group__acronym="ietf")
11+
except Person.DoesNotExist:
12+
return None
13+
14+
15+
def get_iesg_chair():
16+
return get_ietf_chair()
17+
18+
19+
def get_iab_chair():
20+
try:
21+
return Person.objects.get(email__role__name="chair", email__role__group__acronym="iab")
22+
except Person.DoesNotExist:
23+
return None
24+
25+
26+
def get_iab_executive_director():
27+
try:
28+
return Person.objects.get(email__role__name="execdir", email__role__group__acronym="iab")
29+
except Person.DoesNotExist:
30+
return None
31+
32+
33+
def get_person_for_user(user):
34+
return user.get_profile()
35+
36+
37+
def is_areadirector(person):
38+
return bool(Role.objects.filter(email__person=person, name="ad", group__state="active", group__type="area"))
39+
40+
41+
def is_wgchair(person):
42+
return bool(Role.objects.filter(email__person=person, name="chair", group__state="active", group__type="wg"))
43+
44+
45+
def is_wgsecretary(person):
46+
return bool(Role.objects.filter(email__person=person, name="sec", group__state="active", group__type="wg"))
47+
48+
49+
def is_ietfchair(person):
50+
return bool(Role.objects.filter(email__person=person, name="chair", group__acronym="ietf"))
51+
52+
53+
def is_iabchair(person):
54+
return bool(Role.objects.filter(email__person=person, name="chair", group__acronym="iab"))
55+
56+
57+
def is_iab_executive_director(person):
58+
return bool(Role.objects.filter(email__person=person, name="execdir", group__acronym="iab"))
59+
60+
61+
def can_add_outgoing_liaison(user):
62+
person = get_person_for_user(user)
63+
if not person:
64+
return False
65+
66+
if (is_areadirector(person) or is_wgchair(person) or
67+
is_wgsecretary(person) or is_ietfchair(person) or
68+
is_iabchair(person) or is_iab_executive_director(person) or
69+
is_sdo_liaison_manager(person) or is_secretariat(user)):
70+
return True
71+
return False
72+
73+
74+
def is_sdo_liaison_manager(person):
75+
return bool(Role.objects.filter(email__person=person, name="liaiman", group__type="sdo"))
76+
77+
78+
def is_sdo_authorized_individual(person):
79+
return bool(Role.objects.filter(email__person=person, name="auth", group__type="sdo"))
80+
81+
82+
def is_secretariat(user):
83+
return bool(Role.objects.filter(email__person=user.get_profile(), name="auth", group__acronym="secretariat"))
84+
85+
86+
def can_add_incoming_liaison(user):
87+
person = get_person_for_user(user)
88+
if not person:
89+
return False
90+
91+
if (is_sdo_liaison_manager(person) or
92+
is_sdo_authorized_individual(person) or
93+
is_secretariat(user)):
94+
return True
95+
return False
96+
97+
98+
def can_add_liaison(user):
99+
return can_add_incoming_liaison(user) or can_add_outgoing_liaison(user)
100+
101+
102+
def is_sdo_manager_for_outgoing_liaison(person, liaison):
103+
if liaison.from_group and liaison.from_group.type_id == "sdo":
104+
return bool(liaison.from_group.role_set.filter(name="liaiman", email__person=person))
105+
return False
106+
107+
108+
def is_sdo_manager_for_incoming_liaison(person, liaison):
109+
if liaison.to_group and liaison.to_group.type_id == "sdo":
110+
return bool(liaison.to_group.role_set.filter(name="liaiman", email__person=person))
111+
return False
112+
113+
114+
def can_edit_liaison(user, liaison):
115+
if is_secretariat(user):
116+
return True
117+
person = get_person_for_user(user)
118+
if is_sdo_liaison_manager(person):
119+
return (is_sdo_manager_for_outgoing_liaison(person, liaison) or
120+
is_sdo_manager_for_incoming_liaison(person, liaison))
121+
return False

ietf/liaisons/admin.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,14 @@ class LiaisonDetailAdmin(admin.ModelAdmin):
3030
# 'response_contact', 'technical_contact', 'purpose', 'purpose_text', 'deadline_date', 'action_taken',
3131
# 'related_to')
3232
raw_id_fields=['person', 'related_to']
33-
admin.site.register(LiaisonDetail, LiaisonDetailAdmin)
33+
if not settings.USE_DB_REDESIGN_PROXY_CLASSES:
34+
admin.site.register(LiaisonDetail, LiaisonDetailAdmin)
3435

3536

3637
class LiaisonPurposeAdmin(admin.ModelAdmin):
3738
ordering = ('purpose_text', )
38-
admin.site.register(LiaisonPurpose, LiaisonPurposeAdmin)
39+
if not settings.USE_DB_REDESIGN_PROXY_CLASSES:
40+
admin.site.register(LiaisonPurpose, LiaisonPurposeAdmin)
3941

4042

4143
class LiaisonManagersAdmin(admin.ModelAdmin):

ietf/liaisons/models.py

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,8 @@ class Meta:
308308

309309
if settings.USE_DB_REDESIGN_PROXY_CLASSES or hasattr(settings, "IMPORTING_FROM_OLD_SCHEMA"):
310310
from redesign.name.models import LiaisonStatementPurposeName
311-
from redesign.person.models import Person
311+
from redesign.doc.models import Document
312+
from redesign.person.models import Email
312313
from redesign.group.models import Group
313314

314315
class LiaisonStatement(models.Model):
@@ -317,13 +318,14 @@ class LiaisonStatement(models.Model):
317318
body = models.TextField(blank=True)
318319
deadline = models.DateField(null=True, blank=True)
319320

320-
related_to = models.ForeignKey('LiaisonDetail', blank=True, null=True)
321+
related_to = models.ForeignKey('LiaisonStatement', blank=True, null=True)
321322

322-
from_body = models.ForeignKey(Group, related_name="liaisonstatement_from_set", null=True, blank=True, help_text="From body, if it exists")
323+
from_group = models.ForeignKey(Group, related_name="liaisonstatement_from_set", null=True, blank=True, help_text="From body, if it exists")
323324
from_name = models.CharField(max_length=255, help_text="Name of the sender body")
324-
to_body = models.ForeignKey(Group, related_name="liaisonstatement_to_set", null=True, blank=True, help_text="to body, if it exists")
325+
from_contact = models.ForeignKey(Email)
326+
to_group = models.ForeignKey(Group, related_name="liaisonstatement_to_set", null=True, blank=True, help_text="To body, if it exists")
325327
to_name = models.CharField(max_length=255, help_text="Name of the recipient body")
326-
to_contact = models.CharField(blank=True, max_length=255)
328+
to_contact = models.CharField(blank=True, max_length=255, help_text="Contacts at to body")
327329

328330
reply_to = models.CharField(blank=True, max_length=255)
329331

@@ -332,14 +334,26 @@ class LiaisonStatement(models.Model):
332334
cc = models.TextField(blank=True)
333335

334336
submitted = models.DateTimeField(null=True, blank=True)
335-
submitted_by = models.ForeignKey(Person)
336337
modified = models.DateTimeField(null=True, blank=True)
337338
approved = models.DateTimeField(null=True, blank=True)
338339

339340
action_taken = models.BooleanField(default=False)
340341

341-
#submitter_name = models.CharField(blank=True, null=True, max_length=255)
342-
#submitter_email = models.CharField(blank=True, null=True, max_length=255)
342+
attachments = models.ManyToManyField(Document, blank=True)
343343

344+
def name(self):
345+
from django.template.defaultfilters import slugify
346+
if self.from_group:
347+
frm = self.from_group.acronym or self.from_group.name
348+
else:
349+
frm = self.from_name
350+
if self.to_group:
351+
to = self.to_group.acronym or self.to_group.name
352+
else:
353+
to = self.to_name
354+
return slugify("liaison" + " " + self.submitted.strftime("%Y-%m-%d") + " " + frm[:50] + " " + to[:50] + " " + self.title[:115])
355+
344356
def __unicode__(self):
345357
return self.title or "<no title>"
358+
359+
LiaisonDetailOld = LiaisonDetail

ietf/liaisons/proxy.py

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
from redesign.proxy_utils import TranslatingManager
2+
from ietf.liaisons.models import LiaisonStatement
3+
4+
class LiaisonDetailProxy(LiaisonStatement):
5+
objects = TranslatingManager(dict(meeting_num="number"))
6+
7+
def from_object(self, base):
8+
for f in base._meta.fields:
9+
setattr(self, f.name, getattr(base, f.name))
10+
return self
11+
12+
#detail_id = models.AutoField(primary_key=True)
13+
@property
14+
def detail_id(self):
15+
return self.id
16+
#person = models.ForeignKey(PersonOrOrgInfo, null=True, db_column='person_or_org_tag')
17+
@property
18+
def person(self):
19+
return self.submitted_by
20+
#submitted_date = models.DateField(null=True, blank=True)
21+
@property
22+
def submitted_date(self):
23+
return self.submitted.date()
24+
#last_modified_date = models.DateField(null=True, blank=True)
25+
@property
26+
def last_modified_date(self):
27+
return self.modified.date()
28+
#from_id = models.IntegerField(null=True, blank=True)
29+
@property
30+
def from_id(self):
31+
return self.from_group_id
32+
#to_body = models.CharField(blank=True, null=True, max_length=255)
33+
@property
34+
def to_body(self):
35+
return self.to_name
36+
#title = models.CharField(blank=True, null=True, max_length=255) # same name
37+
#response_contact = models.CharField(blank=True, null=True, max_length=255) # same name
38+
#technical_contact = models.CharField(blank=True, null=True, max_length=255) # same name
39+
#purpose_text = models.TextField(blank=True, null=True, db_column='purpose')
40+
@property
41+
def purpose_text(self):
42+
return ""
43+
#body = models.TextField(blank=True,null=True) # same name
44+
#deadline_date = models.DateField(null=True, blank=True)
45+
@property
46+
def deadline_date(self):
47+
return self.deadline.date()
48+
#cc1 = models.TextField(blank=True, null=True)
49+
@property
50+
def cc1(self):
51+
return self.cc
52+
#cc2 = models.CharField(blank=True, null=True, max_length=50) # unused
53+
#submitter_name = models.CharField(blank=True, null=True, max_length=255)
54+
#submitter_email = models.CharField(blank=True, null=True, max_length=255)
55+
#by_secretariat = models.IntegerField(null=True, blank=True)
56+
@property
57+
def by_secretariat(self):
58+
return False
59+
#to_poc = models.CharField(blank=True, null=True, max_length=255)
60+
@property
61+
def to_poc(self):
62+
return self.to_contact
63+
#to_email = models.CharField(blank=True, null=True, max_length=255) # unused
64+
#purpose = models.ForeignKey(LiaisonPurpose,null=True)
65+
#replyto = models.CharField(blank=True, null=True, max_length=255)
66+
@property
67+
def replyto(self):
68+
return self.reply_to
69+
#from_raw_body = models.CharField(blank=True, null=True, max_length=255)
70+
@property
71+
def from_raw_body(self):
72+
return self.from_name
73+
#from_raw_code = models.CharField(blank=True, null=True, max_length=255)
74+
@property
75+
def from_raw_code(self):
76+
return self.from_group_id
77+
#to_raw_code = models.CharField(blank=True, null=True, max_length=255)
78+
@property
79+
def to_raw_code(self):
80+
return self.to_body_id
81+
#approval = models.ForeignKey(OutgoingLiaisonApproval, blank=True, null=True)
82+
@property
83+
def approval(self):
84+
return bool(self.approved)
85+
#action_taken = models.BooleanField(default=False, db_column='taken_care') # same name
86+
#related_to = models.ForeignKey('LiaisonDetail', blank=True, null=True) # same name
87+
def __str__(self):
88+
return unicode(self)
89+
def __unicode__(self):
90+
return self.title or "<no title>"
91+
def from_body(self):
92+
return self.from_name
93+
def from_sdo(self):
94+
return self.from_group if self.from_group and self.from_group.type_id == "sdo" else None
95+
def from_email(self):
96+
self.from_contact
97+
def get_absolute_url(self):
98+
return '/liaison/%d/' % self.detail_id
99+
class Meta:
100+
proxy = True
101+
102+
def notify_pending_by_email(self, fake):
103+
raise NotImplemented
104+
from ietf.liaisons.utils import IETFHM
105+
106+
from_entity = IETFHM.get_entity_by_key(self.from_raw_code)
107+
if not from_entity:
108+
return None
109+
to_email = []
110+
for person in from_entity.can_approve():
111+
to_email.append('%s <%s>' % person.email())
112+
subject = 'New Liaison Statement, "%s" needs your approval' % (self.title)
113+
from_email = settings.LIAISON_UNIVERSAL_FROM
114+
body = render_to_string('liaisons/pending_liaison_mail.txt',
115+
{'liaison': self,
116+
})
117+
mail = IETFEmailMessage(subject=subject,
118+
to=to_email,
119+
from_email=from_email,
120+
body = body)
121+
if not fake:
122+
mail.send()
123+
return mail
124+
125+
def send_by_email(self, fake=False):
126+
raise NotImplemented
127+
if self.is_pending():
128+
return self.notify_pending_by_email(fake)
129+
subject = 'New Liaison Statement, "%s"' % (self.title)
130+
from_email = settings.LIAISON_UNIVERSAL_FROM
131+
to_email = self.to_poc.split(',')
132+
cc = self.cc1.split(',')
133+
if self.technical_contact:
134+
cc += self.technical_contact.split(',')
135+
if self.response_contact:
136+
cc += self.response_contact.split(',')
137+
bcc = ['statements@ietf.org']
138+
body = render_to_string('liaisons/liaison_mail.txt',
139+
{'liaison': self,
140+
})
141+
mail = IETFEmailMessage(subject=subject,
142+
to=to_email,
143+
from_email=from_email,
144+
cc = cc,
145+
bcc = bcc,
146+
body = body)
147+
if not fake:
148+
mail.send()
149+
return mail
150+
151+
def is_pending(self):
152+
return not self.approved

ietf/liaisons/utils.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from django.conf import settings
2+
13
from ietf.idtracker.models import Area, IETFWG
24
from ietf.liaisons.models import SDOs, LiaisonManagers
35
from ietf.liaisons.accounts import (is_ietfchair, is_iabchair, is_iab_executive_director,
@@ -420,3 +422,6 @@ def get_all_can_approve_codes(self, person):
420422

421423

422424
IETFHM = IETFHierarchyManager()
425+
426+
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
427+
from utilsREDESIGN import *

0 commit comments

Comments
 (0)