|
3 | 3 |
|
4 | 4 | import datetime |
5 | 5 | import email.utils |
| 6 | +import json |
6 | 7 | import jsonfield |
7 | 8 | import os |
8 | 9 | import re |
| 10 | +import requests |
| 11 | + |
| 12 | +from jwcrypto import jwk, jws |
| 13 | +from jwcrypto.common import json_encode |
9 | 14 | from urlparse import urljoin |
10 | 15 |
|
| 16 | +from django.conf import settings |
11 | 17 | from django.core.validators import RegexValidator |
12 | 18 | from django.db import models |
13 | 19 | from django.db.models.deletion import CASCADE |
| 20 | +from django.dispatch import receiver |
14 | 21 |
|
15 | 22 | from simple_history.models import HistoricalRecords |
16 | 23 |
|
@@ -349,3 +356,42 @@ def __unicode__(self): |
349 | 356 |
|
350 | 357 | class Meta: |
351 | 358 | verbose_name_plural = "role histories" |
| 359 | + |
| 360 | + |
| 361 | +# --- Signal hooks for group models --- |
| 362 | + |
| 363 | +@receiver(models.signals.pre_save, sender=Group) |
| 364 | +def notify_rfceditor_of_group_name_change(sender, instance=None, **kwargs): |
| 365 | + if instance: |
| 366 | + try: |
| 367 | + current = Group.objects.get(pk=instance.pk) |
| 368 | + except Group.DoesNotExist: |
| 369 | + return |
| 370 | + url = settings.RFC_EDITOR_GROUP_NOTIFICATION_URL |
| 371 | + if url and instance.name != current.name: |
| 372 | + data = { |
| 373 | + 'acronym': current.acronym, |
| 374 | + 'old_name': current.name, |
| 375 | + 'name': instance.name, |
| 376 | + } |
| 377 | + # Build signed data |
| 378 | + key = jwk.JWK() |
| 379 | + key.import_from_pem(settings.API_PRIVATE_KEY_PEM) |
| 380 | + payload = json.dumps(data) |
| 381 | + jwstoken = jws.JWS(payload.encode('utf-8')) |
| 382 | + jwstoken.add_signature(key, None, |
| 383 | + json_encode({"alg": settings.API_KEY_TYPE}), |
| 384 | + json_encode({"kid": key.thumbprint()})) |
| 385 | + sig = jwstoken.serialize() |
| 386 | + # Send signed data |
| 387 | + response = requests.post(url, data = { 'jws': sig, }) |
| 388 | + log.log("Sent notify: %s: '%s' --> '%s' to %s, result code %s" % |
| 389 | + (current.acronym, current.name, instance.name, url, response.status_code)) |
| 390 | + # Verify locally, to make sure we've got things right |
| 391 | + key = jwk.JWK() |
| 392 | + key.import_from_pem(settings.API_PUBLIC_KEY_PEM) |
| 393 | + jwstoken = jws.JWS() |
| 394 | + jwstoken.deserialize(sig) |
| 395 | + jwstoken.verify(key) |
| 396 | + log.assertion('payload == jwstoken.payload') |
| 397 | + |
0 commit comments