Skip to content

Commit 1e11553

Browse files
committed
The previous nomcom.fields.EncryptedTextField relied on initial cleartext content having the same type as ciphertext. Under Python3, that's not the case (ciphertext has type bytes). Rewrote the nomcom app and tests to handle capture of comments and encryption to the Feedback.comments ciphertext differently.
- Legacy-Id: 16350
1 parent f76d8bf commit 1e11553

7 files changed

Lines changed: 77 additions & 52 deletions

File tree

ietf/nomcom/factories.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# Copyright The IETF Trust 2015-2019, All Rights Reserved
12
import factory
23
import random
34

@@ -164,9 +165,13 @@ class Meta:
164165

165166
nomcom = factory.SubFactory(NomComFactory)
166167
subject = factory.Faker('sentence')
167-
comments = factory.Faker('paragraph')
168168
type_id = 'comment'
169169

170+
@factory.post_generation
171+
def comments(obj, create, extracted, **kwargs):
172+
comment_text = factory.Faker('paragraph').generate()
173+
obj.comments = obj.nomcom.encrypt(comment_text)
174+
170175
class TopicFactory(factory.DjangoModelFactory):
171176
class Meta:
172177
model = Topic

ietf/nomcom/forms.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ def save(self, commit=True):
293293

294294
# Complete nomination data
295295
feedback = Feedback.objects.create(nomcom=self.nomcom,
296-
comments=qualifications,
296+
comments=self.nomcom.encrypt(qualifications),
297297
type=FeedbackTypeName.objects.get(slug='nomina'),
298298
user=self.user)
299299
feedback.positions.add(position)
@@ -408,7 +408,7 @@ def save(self, commit=True):
408408

409409
# Complete nomination data
410410
feedback = Feedback.objects.create(nomcom=self.nomcom,
411-
comments=qualifications,
411+
comments=self.nomcom.encrypt(qualifications),
412412
type=FeedbackTypeName.objects.get(slug='nomina'),
413413
user=self.user)
414414
feedback.positions.add(position)
@@ -451,7 +451,7 @@ class Meta:
451451

452452
class FeedbackForm(forms.ModelForm):
453453
nominator_email = forms.CharField(label='Commenter email',required=False)
454-
comments = forms.CharField(label='Comments', widget=forms.Textarea(), strip=False)
454+
comment_text = forms.CharField(label='Comments', widget=forms.Textarea(), strip=False)
455455
confirmation = forms.BooleanField(label='Email comments back to me as confirmation (if selected, your comments will be emailed to you in cleartext when you press Save).',
456456
required=False)
457457

@@ -484,13 +484,13 @@ def clean(self):
484484
if not NomineePosition.objects.accepted().filter(nominee=self.nominee,
485485
position=self.position):
486486
msg = "There isn't a accepted nomination for %s on the %s position" % (self.nominee, self.position)
487-
self._errors["comments"] = self.error_class([msg])
487+
self._errors["comment_text"] = self.error_class([msg])
488488
return self.cleaned_data
489489

490490
def save(self, commit=True):
491491
feedback = super(FeedbackForm, self).save(commit=False)
492492
confirmation = self.cleaned_data['confirmation']
493-
comments = self.cleaned_data['comments']
493+
comment_text = self.cleaned_data['comment_text']
494494
nomcom_template_path = '/nomcom/%s/' % self.nomcom.group.acronym
495495

496496
author = None
@@ -508,6 +508,7 @@ def save(self, commit=True):
508508
feedback.nomcom = self.nomcom
509509
feedback.user = self.user
510510
feedback.type = FeedbackTypeName.objects.get(slug='comment')
511+
feedback.comments = self.nomcom.encrypt(comment_text)
511512
feedback.save()
512513
if self.nominee and self.position:
513514
feedback.positions.add(self.position)
@@ -526,7 +527,7 @@ def save(self, commit=True):
526527
elif self.topic:
527528
about = self.topic.subject
528529
context = {'about': about,
529-
'comments': comments,
530+
'comments': comment_text,
530531
'year': self.nomcom.year(),
531532
}
532533
path = nomcom_template_path + FEEDBACK_RECEIPT_TEMPLATE
@@ -537,7 +538,6 @@ class Meta:
537538
model = Feedback
538539
fields = (
539540
'nominator_email',
540-
'comments',
541541
'confirmation',
542542
)
543543

@@ -554,8 +554,9 @@ def save(self, commit=True):
554554

555555
class QuestionnaireForm(forms.ModelForm):
556556

557-
comments = forms.CharField(label='Questionnaire response from this candidate',
557+
comment_text = forms.CharField(label='Questionnaire response from this candidate',
558558
widget=forms.Textarea(), strip=False)
559+
559560
def __init__(self, *args, **kwargs):
560561
self.nomcom = kwargs.pop('nomcom', None)
561562
self.user = kwargs.pop('user', None)
@@ -565,6 +566,7 @@ def __init__(self, *args, **kwargs):
565566

566567
def save(self, commit=True):
567568
feedback = super(QuestionnaireForm, self).save(commit=False)
569+
comment_text = self.cleaned_data['comment_text']
568570
(position, nominee) = self.cleaned_data['nominee']
569571

570572
author = get_user_email(self.user)
@@ -575,14 +577,15 @@ def save(self, commit=True):
575577
feedback.nomcom = self.nomcom
576578
feedback.user = self.user
577579
feedback.type = FeedbackTypeName.objects.get(slug='questio')
580+
feedback.comments = self.nomcom.encrypt(comment_text)
578581
feedback.save()
579582
self.save_m2m()
580583
feedback.nominees.add(nominee)
581584
feedback.positions.add(position)
582585

583586
class Meta:
584587
model = Feedback
585-
fields = ( 'comments', )
588+
fields = []
586589

587590
class NomComTemplateForm(DBTemplateForm):
588591
content = forms.CharField(label="Text", widget=forms.Textarea(attrs={'cols': '120', 'rows':'40', }), strip=False)

ietf/nomcom/models.py

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,20 @@
1111

1212
import debug # pyflakes:ignore
1313

14-
from ietf.nomcom.fields import EncryptedTextField
1514
from ietf.person.models import Person,Email
1615
from ietf.group.models import Group
1716
from ietf.name.models import NomineePositionStateName, FeedbackTypeName, TopicAudienceName
1817
from ietf.dbtemplate.models import DBTemplate
1918

20-
from ietf.nomcom.managers import NomineePositionManager, NomineeManager, \
21-
PositionManager, FeedbackManager
19+
from ietf.nomcom.managers import (NomineePositionManager, NomineeManager,
20+
PositionManager, FeedbackManager, )
2221
from ietf.nomcom.utils import (initialize_templates_for_group,
2322
initialize_questionnaire_for_position,
2423
initialize_requirements_for_position,
2524
initialize_description_for_topic,
2625
delete_nomcom_templates)
2726
from ietf.utils.models import ForeignKey
27+
from ietf.utils.pipe import pipe
2828
from ietf.utils.storage import NoLocationMigrationFileSystemStorage
2929

3030

@@ -79,6 +79,21 @@ def year(self):
7979
def pending_email_count(self):
8080
return self.feedback_set.filter(type__isnull=True).count()
8181

82+
def encrypt(self, cleartext:str) -> bytes:
83+
try:
84+
cert_file = self.public_key.path
85+
except ValueError as e:
86+
raise ValueError("Trying to read the NomCom public key: " + str(e))
87+
88+
command = "%s smime -encrypt -in /dev/stdin %s" % (settings.OPENSSL_COMMAND, cert_file)
89+
code, out, error = pipe(command, cleartext.encode())
90+
if code != 0:
91+
log("openssl error: %s:\n Error %s: %s" %(command, code, error))
92+
if not error:
93+
return out
94+
else:
95+
raise EncryptedException(error)
96+
8297

8398
def delete_nomcom(sender, **kwargs):
8499
nomcom = kwargs.get('instance', None)
@@ -250,7 +265,7 @@ class Feedback(models.Model):
250265
nominees = models.ManyToManyField('Nominee', blank=True)
251266
topics = models.ManyToManyField('Topic', blank=True)
252267
subject = models.TextField(verbose_name='Subject', blank=True)
253-
comments = EncryptedTextField(verbose_name='Comments')
268+
comments = models.BinaryField(verbose_name='Comments')
254269
type = ForeignKey(FeedbackTypeName, blank=True, null=True)
255270
user = ForeignKey(User, editable=False, blank=True, null=True, on_delete=models.SET_NULL)
256271
time = models.DateTimeField(auto_now_add=True)

ietf/nomcom/resources.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ class Meta:
129129
"id": ALL,
130130
"author": ALL,
131131
"subject": ALL,
132-
"comments": ALL,
132+
# "comments": ALL,
133133
"time": ALL,
134134
"nomcom": ALL_WITH_RELATIONS,
135135
"type": ALL_WITH_RELATIONS,

0 commit comments

Comments
 (0)