Skip to content

Commit 63bc9cf

Browse files
committed
Changes from esanchez@yaco.es, changesets 2783-2789. Lets the secretariat send liaisons on behalf of others, corrected powers to liaison managers, and other fixes.
- Legacy-Id: 2800
2 parents 5aa8011 + d77970d commit 63bc9cf

9 files changed

Lines changed: 320 additions & 17 deletions

File tree

changelog

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,34 @@ ietfdb (3.12)
1818
* Renamed 'LiaisonDetail.taken_care' field to 'action_taken'.
1919
Miscellaneous associated fixes. Enhanced liaison-related admin pages.
2020

21+
Note: Deploying this release requires additional steps; to verify
22+
that liaison related settings in settings.py are correct, and to create
23+
new tables and update existing tables and table content. The latter
24+
is done as South migrations (see http://south.aeracode.org/ for more
25+
info on the South app). More extensiive documentation about the actions
26+
needed are provided in the user manual (doc/LSMT_user_manual.pdf in
27+
the release). The brief version follows:
28+
29+
# 8<----------
30+
# First the regular checkout and prepare:
31+
32+
cd /a/www/ietf-datatracker
33+
svn co http://svn.tools.ietf.org/svn/tools/ietfdb/tags/3.12
34+
cp web/ietf/settings_local.py 3.12/ietf/
35+
cd 3.12
36+
37+
# Next, apply the migrations:
38+
39+
PYTHONPATH=$PWD ietf/manage.py migrate liaisons
40+
41+
# Then carry on with the usual actions:
42+
43+
cd ../
44+
rm ./web; ln -s 3.12 web
45+
sudo /etc/init.d/apache restart
46+
47+
# 8<----------
48+
2149
-- Henrik Levkowetz <henrik@levkowetz.com> 28 Jan 2011 13:15:40 +0100
2250

2351
ietfdb (3.11)

ietf/liaisons/accounts.py

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
from ietf.idtracker.models import Role, PersonOrOrgInfo
22

33

4-
LIAISON_EDIT_GROUPS = ['Liaison_Manager', 'Secretariat']
4+
LIAISON_EDIT_GROUPS = ['Secretariat']
5+
56

67
def get_ietf_chair():
78
person = PersonOrOrgInfo.objects.filter(role=Role.IETF_CHAIR)
@@ -65,7 +66,7 @@ def can_add_outgoing_liaison(user):
6566
if (is_areadirector(person) or is_wgchair(person) or
6667
is_wgsecretary(person) or is_ietfchair(person) or
6768
is_iabchair(person) or is_iab_executive_director(person) or
68-
is_ietf_liaison_manager(user)):
69+
is_sdo_liaison_manager(person) or is_secretariat(user)):
6970
return True
7071
return False
7172

@@ -78,8 +79,8 @@ def is_sdo_authorized_individual(person):
7879
return bool(person.sdoauthorizedindividual_set.all())
7980

8081

81-
def is_ietf_liaison_manager(user):
82-
return bool(user.groups.filter(name='Liaison_Manager'))
82+
def is_secretariat(user):
83+
return bool(user.groups.filter(name='Secretariat'))
8384

8485

8586
def can_add_incoming_liaison(user):
@@ -89,10 +90,51 @@ def can_add_incoming_liaison(user):
8990

9091
if (is_sdo_liaison_manager(person) or
9192
is_sdo_authorized_individual(person) or
92-
is_ietf_liaison_manager(user)):
93+
is_secretariat(user)):
9394
return True
9495
return False
9596

9697

9798
def can_add_liaison(user):
9899
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+
from ietf.liaisons.utils import IETFHM, SDOEntity
104+
from ietf.liaisons.models import SDOs
105+
from_entity = IETFHM.get_entity_by_key(liaison.from_raw_code)
106+
sdo = None
107+
if not from_entity:
108+
sdo = SDOs.objects.get(sdo_name=liaison.from_body())
109+
elif isinstance(from_entity, SDOEntity):
110+
sdo = from_entity.obj
111+
if sdo:
112+
return bool(sdo.liaisonmanagers_set.filter(person=person))
113+
return False
114+
115+
116+
def is_sdo_manager_for_incoming_liaison(person, liaison):
117+
from ietf.liaisons.utils import IETFHM, SDOEntity
118+
from ietf.liaisons.models import SDOs
119+
to_entity = IETFHM.get_entity_by_key(liaison.to_raw_code)
120+
sdo = None
121+
if not to_entity:
122+
try:
123+
sdo = SDOs.objects.get(sdo_name=liaison.to_body)
124+
except SDOs.DoesNotExist:
125+
pass
126+
elif isinstance(to_entity, SDOEntity):
127+
sdo = to_entity.obj
128+
if sdo:
129+
return bool(sdo.liaisonmanagers_set.filter(person=person))
130+
return False
131+
132+
133+
def can_edit_liaison(user, liaison):
134+
if is_secretariat(user):
135+
return True
136+
person = get_person_for_user(user)
137+
if is_sdo_liaison_manager(person):
138+
return (is_sdo_manager_for_outgoing_liaison(person, liaison) or
139+
is_sdo_manager_for_incoming_liaison(person, liaison))
140+
return False

ietf/liaisons/forms.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@
88
from django.forms.fields import email_re
99
from django.template.loader import render_to_string
1010

11+
from ietf.idtracker.models import PersonOrOrgInfo
1112
from ietf.liaisons.accounts import (can_add_outgoing_liaison, can_add_incoming_liaison,
12-
get_person_for_user, is_ietf_liaison_manager)
13+
get_person_for_user, is_secretariat, is_sdo_liaison_manager)
1314
from ietf.liaisons.models import LiaisonDetail, Uploads, OutgoingLiaisonApproval, SDOs
1415
from ietf.liaisons.utils import IETFHM
1516
from ietf.liaisons.widgets import (FromWidget, ReadOnlyWidget, ButtonWidget,
@@ -61,6 +62,9 @@ def __init__(self, user, *args, **kwargs):
6162
self.person = get_person_for_user(user)
6263
if kwargs.get('data', None):
6364
kwargs['data'].update({'person': self.person.pk})
65+
if is_secretariat(self.user) and 'from_fake_user' in kwargs['data'].keys():
66+
fake_person = PersonOrOrgInfo.objects.get(pk=kwargs['data']['from_fake_user'])
67+
kwargs['data'].update({'person': fake_person.pk})
6468
super(LiaisonForm, self).__init__(*args, **kwargs)
6569
self.hm = IETFHM
6670
self.set_from_field()
@@ -186,6 +190,7 @@ def save_extra_fields(self, liaison):
186190
liaison.from_raw_body = from_entity.name
187191
liaison.from_raw_code = self.cleaned_data.get('from_field')
188192
organization = self.get_to_entity()
193+
liaison.to_raw_code = self.cleaned_data.get('organization')
189194
liaison.to_body = organization.name
190195
liaison.to_poc = self.get_poc(organization)
191196
liaison.submitter_name, liaison.submitter_email = self.person.email()
@@ -228,7 +233,7 @@ def clean_title(self):
228233
class IncomingLiaisonForm(LiaisonForm):
229234

230235
def set_from_field(self):
231-
if is_ietf_liaison_manager(self.user):
236+
if is_secretariat(self.user):
232237
sdos = SDOs.objects.all()
233238
else:
234239
sdo_managed = [i.sdo for i in self.person.liaisonmanagers_set.all()]
@@ -241,7 +246,8 @@ def set_organization_field(self):
241246
self.fields['organization'].choices = self.hm.get_all_incoming_entities()
242247

243248
def get_post_only(self):
244-
if self.user.groups.filter(name='Liaison_Manager'):
249+
from_entity = self.get_from_entity()
250+
if self.person.liaisonmanagers_set.filter(sdo=from_entity.obj):
245251
return True
246252
return False
247253

@@ -265,15 +271,19 @@ def get_to_entity(self):
265271
return organization
266272

267273
def set_from_field(self):
268-
if is_ietf_liaison_manager(self.user):
274+
if is_secretariat(self.user) or is_sdo_liaison_manager(self.person):
269275
self.fields['from_field'].choices = self.hm.get_all_incoming_entities()
270276
else:
271277
self.fields['from_field'].choices = self.hm.get_entities_for_person(self.person)
272278
self.fields['from_field'].widget.submitter = unicode(self.person)
273279
self.fieldsets[0] = ('From', ('from_field', 'replyto', 'approved'))
274280

275281
def set_organization_field(self):
276-
self.fields['organization'].choices = self.hm.get_all_outgoing_entities()
282+
if is_sdo_liaison_manager(self.person):
283+
sdos = [i.sdo for i in self.person.liaisonmanagers_set.all().distinct()]
284+
self.fields['organization'].choices = [('sdo_%s' % i.pk, i.sdo_name) for i in sdos]
285+
else:
286+
self.fields['organization'].choices = self.hm.get_all_outgoing_entities()
277287
self.fieldsets[1] = ('To', ('organization', 'other_organization', 'to_poc'))
278288

279289
def set_required_fields(self):
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
2+
from south.db import db
3+
from django.db import models
4+
from ietf.liaisons.models import *
5+
6+
class Migration:
7+
8+
def forwards(self, orm):
9+
10+
# Adding field 'LiaisonDetail.to_raw_code'
11+
db.add_column('liaison_detail', 'to_raw_code', orm['liaisons.liaisondetail:to_raw_code'])
12+
13+
14+
15+
def backwards(self, orm):
16+
17+
# Deleting field 'LiaisonDetail.to_raw_code'
18+
db.delete_column('liaison_detail', 'to_raw_code')
19+
20+
21+
22+
models = {
23+
'idtracker.personororginfo': {
24+
'Meta': {'db_table': "'person_or_org_info'"},
25+
'address_type': ('django.db.models.fields.CharField', [], {'max_length': '4', 'null': 'True', 'blank': 'True'}),
26+
'created_by': ('django.db.models.fields.CharField', [], {'max_length': '8', 'null': 'True', 'blank': 'True'}),
27+
'date_created': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
28+
'date_modified': ('django.db.models.fields.DateField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}),
29+
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}),
30+
'first_name_key': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}),
31+
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
32+
'last_name_key': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
33+
'middle_initial': ('django.db.models.fields.CharField', [], {'max_length': '4', 'null': 'True', 'blank': 'True'}),
34+
'middle_initial_key': ('django.db.models.fields.CharField', [], {'max_length': '4', 'null': 'True', 'blank': 'True'}),
35+
'modified_by': ('django.db.models.fields.CharField', [], {'max_length': '8', 'null': 'True', 'blank': 'True'}),
36+
'name_prefix': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
37+
'name_suffix': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
38+
'person_or_org_tag': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
39+
'record_type': ('django.db.models.fields.CharField', [], {'max_length': '8', 'null': 'True', 'blank': 'True'})
40+
},
41+
'liaisons.frombodies': {
42+
'Meta': {'db_table': "'from_bodies'"},
43+
'body_name': ('django.db.models.fields.CharField', [], {'max_length': '35', 'blank': 'True'}),
44+
'email_priority': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
45+
'from_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
46+
'is_liaison_manager': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
47+
'other_sdo': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
48+
'poc': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'null': 'True', 'db_column': "'poc'"})
49+
},
50+
'liaisons.liaisondetail': {
51+
'Meta': {'db_table': "'liaison_detail'"},
52+
'approval': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['liaisons.OutgoingLiaisonApproval']", 'null': 'True', 'blank': 'True'}),
53+
'body': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
54+
'by_secretariat': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
55+
'cc1': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
56+
'cc2': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
57+
'deadline_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
58+
'detail_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
59+
'from_id': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
60+
'from_raw_body': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
61+
'from_raw_code': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
62+
'last_modified_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
63+
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'null': 'True', 'db_column': "'person_or_org_tag'"}),
64+
'purpose': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['liaisons.LiaisonPurpose']", 'null': 'True'}),
65+
'purpose_text': ('django.db.models.fields.TextField', [], {'null': 'True', 'db_column': "'purpose'", 'blank': 'True'}),
66+
'related_to': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['liaisons.LiaisonDetail']", 'null': 'True', 'blank': 'True'}),
67+
'replyto': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
68+
'response_contact': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
69+
'submitted_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
70+
'submitter_email': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
71+
'submitter_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
72+
'taken_care': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
73+
'technical_contact': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
74+
'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
75+
'to_body': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
76+
'to_email': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
77+
'to_poc': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
78+
'to_raw_code': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'})
79+
},
80+
'liaisons.liaisonmanagers': {
81+
'Meta': {'db_table': "'liaison_managers'"},
82+
'email_priority': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
83+
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
84+
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'db_column': "'person_or_org_tag'"}),
85+
'sdo': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['liaisons.SDOs']"})
86+
},
87+
'liaisons.liaisonpurpose': {
88+
'Meta': {'db_table': "'liaison_purpose'"},
89+
'purpose_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
90+
'purpose_text': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'})
91+
},
92+
'liaisons.outgoingliaisonapproval': {
93+
'approval_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
94+
'approved': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
95+
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
96+
},
97+
'liaisons.sdoauthorizedindividual': {
98+
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
99+
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'db_column': "'person_or_org_tag'"}),
100+
'sdo': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['liaisons.SDOs']"})
101+
},
102+
'liaisons.sdos': {
103+
'Meta': {'db_table': "'sdos'"},
104+
'sdo_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
105+
'sdo_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'})
106+
},
107+
'liaisons.uploads': {
108+
'Meta': {'db_table': "'uploads'"},
109+
'detail': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['liaisons.LiaisonDetail']"}),
110+
'file_extension': ('django.db.models.fields.CharField', [], {'max_length': '10', 'blank': 'True'}),
111+
'file_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
112+
'file_title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
113+
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['idtracker.PersonOrOrgInfo']", 'db_column': "'person_or_org_tag'"})
114+
}
115+
}
116+
117+
complete_apps = ['liaisons']

ietf/liaisons/models.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ class LiaisonDetail(models.Model):
6464
replyto = models.CharField(blank=True, null=True, max_length=255)
6565
from_raw_body = models.CharField(blank=True, null=True, max_length=255)
6666
from_raw_code = models.CharField(blank=True, null=True, max_length=255)
67+
to_raw_code = models.CharField(blank=True, null=True, max_length=255)
6768
approval = models.ForeignKey(OutgoingLiaisonApproval, blank=True, null=True)
6869
action_taken = models.BooleanField(default=False, db_column='taken_care')
6970
related_to = models.ForeignKey('LiaisonDetail', blank=True, null=True)

0 commit comments

Comments
 (0)